我有以下两个接口,一个允许可以为空的 vin
,另一个不允许:
interface IVehicle {
vin: string | null;
model: string;
}
interface IVehicleNonNullVin {
vin: string;
model: string;
}
我希望能够在我能够推断出 IVehicle
不是 IVehicleNonNullVin
的执行路径中将模型从 vin
转换为 null
。>
考虑这个例子:
const myVehicle: IVehicle = {
vin: 'abc123',
model: 'm3'
};
const needsVin = (_: IVehicleNonNullVin) => false;
if (myVehicle.vin === null) {
throw new Error('null');
} else {
needsVin(myVehicle);
// ~~~~~~~~~~~~~~~~~~~ 'IVehicle' is not assignable to 'IVehicleNonNullVin'
}
返回以下错误:
<块引用>“IVehicle”类型的参数不可分配给“IVehicleNonNullVin”类型的参数。
属性“vin”的类型不兼容。
输入'字符串| null' 不可分配给类型 'string'。
类型 'null' 不能分配给类型 'string'。
即使我肯定,这里的属性也不能为空。
问:我如何根据代码流中的类型检查让 TS 相信现有模型符合类型?
作为一种解决方法,我可以强制转换类型(但忽略了现有的类型安全):
needsVin(myVehicle as IVehicleNonNullVin);
或者构建一个新模型(但这不能很好地扩展很多属性):
const nonNullVehicle: IVehicleNonNullVin = {
model: myVehicle.model,
vin: myVehicle.vin
}
needsVin(nonNullVehicle);
答案 0 :(得分:2)
您可以使用 type predicate 来定义用户定义的类型保护,如下所示:
export function useParams<T extends string>(
expected: T[]
): { [key in T as NonOptional<T>]: string } {
// ... our custom implementation
return null as any;
}
type NonOptional<T extends string> = T extends `?${infer Inner}` ? Inner : T;
// Should produce type { a: string; b: string | undefined }
const result = useParams(['a', '?b']);
<块引用>
如果原始类型兼容,TypeScript 会缩小该变量到该特定类型。