我有以下应该编译的代码,但它不是:
interface A {
field: string;
fieldB: { fieldC: string;}
}
function mixPropValue<P extends keyof A>(propName: P, value: A[P]) {
if (propName === 'fieldB') {
// value is always in type of { fieldC:string }
value.fieldC; // Error: Property 'fieldC' does not exist on type 'A[P]'.
}
}
是否可以让TypeScript知道第一个if
分支下的缩小类型?当然我可以使用类型转换来编译代码,但我想避免它。
答案 0 :(得分:1)
您可以缩小与检查属性名称相同匹配的类型,以便将类型解析为更窄的选项:
interface A {
field: string;
fieldB: { fieldC: string;}
}
function isFieldB<P extends keyof A>(propName: P, prop: { fieldC: string } | any): prop is { fieldC: string } {
return propName === 'fieldB';
}
function mixPropValue<P extends keyof A>(propName: P, value: A[P]) {
if (isFieldB(propName, value)) {
value.fieldC;
}
}
编译器的未来版本可能会使这种情况变得多余,但如果他们这样做会有一个令人印象深刻的飞跃,因为有合理数量的&#34;连接点&#34;这里。 TypeScript团队经常管理它。
答案 1 :(得分:0)
编译器不会根据suck测试缩小类型,最好的选择是自定义类型保护:
function isProp<P extends keyof A>(value: A[keyof A], targetProp: P, testProp : keyof A) : value is A[P] {
return targetProp === testProp;
}
function mixPropValue<P extends keyof A>(propName: P, oldValue: A[P], newValue: A[P]) {
if (isProp(oldValue, 'fieldB', propName) && isProp(newValue, 'fieldB', propName)) {
// oldValue, newValue here are always in type of { fieldC:string }
return { ...oldValue, ...newValue }; // Error: Spread types may only be created from object types.
}
return newValue;
}