如何让TypeScript中两个组件识别其属性类型匹配?
TypeScript类型关联问题:如何让数组与元素的类型和type参数联动?
这是针对「如何让TypeScript识别某一参数可作为另一对象参数的区分属性?」的跟进提问,问题通过以下代码示例说明:
type Types = "Foo" | "Bar"; interface ObjOne { one: "one"; two: "two"; } interface ObjTwo { three: "three"; four: "four"; } type ExtractRelatedObject<T extends Types> = T extends "Foo" ? ObjOne : T extends "Bar" ? ObjTwo : never; interface Baz<T extends Types> { type: T; relatedObject: ExtractRelatedObject<T>; arrayOfRelatedObject: Array<ExtractRelatedObject<T>> } function componentOne({type, relatedObject, arrayOfRelatedObject}: Baz<"Foo"> | Baz<"Bar">) { if (type === "Bar") { relatedObject.three; arrayOfRelatedObject.map(relObj => relObj) } } interface ComponentTwoProps<T extends Types> { type: T arrayOfRelatedObject: Array<ExtractRelatedObject<T>> } function componentTwo<T extends Types>({type, arrayOfRelatedObject}: ComponentTwoProps<T>) { arrayOfRelatedObject.map((relObj, index, arr) => { return componentOne({type, relatedObject: relObj, arrayOfRelatedObject: arr }) }) }
问题描述
在componentTwo中调用componentOne时,TypeScript无法识别arr(数组)、relObj(数组元素)与type参数之间的关联,导致类型不匹配报错。尝试了原问题中的交叉分配方案,但并未解决问题。
问题原因
componentTwo被定义为泛型函数,泛型参数T是Types的宽泛约束(可以是"Foo"、"Bar"或两者的联合)。当T为联合类型时,arrayOfRelatedObject的类型会变成Array<ObjOne | ObjTwo>,而非对应单一类型的数组。此时TypeScript无法将type、relObj和arr的类型绑定到Baz的具体分支上,自然无法通过类型检查。
修复方案
将componentTwo的参数类型从泛型约束改为联合类型,让TypeScript能够对type进行类型窄化,自动关联对应分支的数组和元素类型:
// 修改componentTwo的参数类型为联合类型 function componentTwo({type, arrayOfRelatedObject}: ComponentTwoProps<"Foo"> | ComponentTwoProps<"Bar">) { return arrayOfRelatedObject.map((relObj, index, arr) => { return componentOne({type, relatedObject: relObj, arrayOfRelatedObject: arr }) }) }
这样修改后,当type为"Foo"时,TypeScript会自动推断arrayOfRelatedObject是ObjOne[]、relObj是ObjOne;当type为"Bar"时,对应类型会自动切换为ObjTwo[]和ObjTwo,完全符合componentOne的参数要求,类型报错即可消除。
内容的提问来源于stack exchange,提问作者Magnus
相关产品推荐
相关产品推荐

