TypeScript自定义类型:为何UndefinedAsString2无法转换undefined为string
问题核心原因
问题出在TypeScript分布式条件类型的触发规则:
- 只有当
extends关键字左侧是完全裸露的泛型类型参数(没有被索引访问、数组、包装类型等其他语法包裹)时,TS才会对传入的联合类型执行「拆分每个成员单独判断、最后合并所有结果为联合类型」的分发逻辑。 - 你写的
UndefinedAsString<T>中,extends左侧是裸泛型参数T,满足分发条件:传入object[] | undefined时,会拆成object[]、undefined两个分支分别判断,最终得到object[] | string,因此赋值字符串'test'符合类型约束,校验通过。 - 而
UndefinedAsString2里的判断逻辑是T[K] extends undefined ? string : T[K],这里extends左侧是索引访问得到的类型T[K],不是裸泛型参数,不会触发联合分发:TS会把object[] | undefined作为一个整体判断是否继承自undefined,显然这个联合包含非undefined成员,整体不满足约束,因此直接返回原类型object[] | undefined,自然无法赋值字符串类型的'test',抛出类型错误。
修复方案
直接复用已经符合预期的UndefinedAsString工具类型处理属性值即可,它的裸泛型参数可以正确触发联合分发:
type UndefinedAsString<T> = T extends undefined ? string : T; type UndefinedAsString2<T extends Record<string, any>> = { [K in keyof T]: UndefinedAsString<T[K]>; }; // 修复后以下代码可正常通过类型校验 const z: UndefinedAsString2<{ x: object[] | undefined }> = { x: 'test' }; // ok
内容的提问来源于stack exchange,提问作者Nico
相关产品推荐
相关产品推荐

