TypeScript基于枚举的嵌套条件类型对象实例化报错求助
TypeScript联合类型返回值类型不兼容问题解决
问题背景
项目中需要使用以下联合类型:
type MyObjectType = { vtype: "text"; vvalues: string[]; } | { vtype: "num1"; vvalues: number[]; } | { vtype: "num2"; vvalues: number[]; }
通过枚举重构后得到如下代码:
enum MyValues { TEXT = 'text', NUM1 = 'num1', NUM2 = 'num2' } type MyValueTypes = `${MyValues}` type MyValue<T extends MyValueTypes> = T extends 'num1' | 'num2' ? number : T extends 'text' ? string : never; type ObjImpl<T> = T extends MyValueTypes ? { vtype: T; vvalues: MyValue<T>[]; } : never; type MyObjectType = ObjImpl<MyValueTypes>;
编写实例化函数时,函数调用的类型校验正常,但返回值出现类型不兼容错误:
function fillProps<T extends MyValueTypes>(vtype: T, item: MyValue<T>): MyObjectType { return { vtype, // ERROR: Type '(string | number)[]' is not assignable to type 'string[] | number[]'. vvalues: [item] } } fillProps(MyValues.TEXT, 78) // ERROR: 符合预期 fillProps(MyValues.NUM1, 78) // 符合预期 fillProps(MyValues.TEXT, 'asd') // 符合预期 fillProps(MyValues.NUM2, 'asd') // ERROR: 符合预期
解决方法
方法1:调整函数返回类型为具体泛型类型
将函数返回类型从MyObjectType改为ObjImpl<T>,让TypeScript精确推断返回值的具体类型,而非笼统的联合类型:
function fillProps<T extends MyValueTypes>(vtype: T, item: MyValue<T>): ObjImpl<T> { return { vtype, vvalues: [item] } }
此时返回值会自动匹配T对应的具体子类型,完全符合类型定义,不再出现错误。
方法2:使用类型断言
如果需要保持返回类型为MyObjectType,可以通过类型断言明确告知TypeScript返回值符合目标类型:
function fillProps<T extends MyValueTypes>(vtype: T, item: MyValue<T>): MyObjectType { return { vtype, vvalues: [item] } as ObjImpl<T>; }
ObjImpl<T>是MyObjectType的子类型,该断言安全且能解决类型推断模糊的问题。
问题原因
函数内部TypeScript无法将泛型T对应的MyValue<T>[]精确推断为string[]或number[],只会推断为(string | number)[]。而(string | number)[](元素可混存字符串/数字的数组)与string[] | number[](全字符串或全数字数组的联合)是不同类型,前者无法直接赋值给后者,因此触发类型错误。通过让返回类型更具体或使用断言,即可消除这种类型推断的模糊性。
内容的提问来源于stack exchange,提问作者pergy
相关产品推荐
相关产品推荐

