条件类型能否检测类型参数是否因无候选实参而使用默认值?
区分TypeScript类型参数是值推导还是默认约束得到的
问题场景
你希望在TypeScript类型系统中区分:类型参数是从具体值推导而来,还是因为未提供对应属性而 fallback 到类型约束的范围。当前代码中X1和X2结果一致,无法区分两种场景:
type Test<A extends string | number> = { a?: A } type Infer<T extends Test<any>> = T extends Test<infer A> ? A : never const v1 = {} const v2 = { a: 'a' as string | number } type X1 = Infer<typeof v1> // 当前结果:string | number type X2 = Infer<typeof v2> // 当前结果:string | number
解决方案
可以通过精确判断类型是否包含明确的a属性来区分这两种情况。利用TypeScript条件类型的属性匹配特性,对未提供a的场景返回自定义标记类型:
type Test<A extends string | number> = { a?: A } type Infer<T extends Test<any>> = // 匹配明确包含a属性的类型,推导实际A类型 T extends { a: infer A } ? A : // 匹配未提供a属性的空对象,返回标记类型(也可以换成never等) T extends {} ? 'DerivedFromConstraint' : never const v1 = {} const v2 = { a: 'a' as string | number } type X1 = Infer<typeof v1> // "DerivedFromConstraint" type X2 = Infer<typeof v2> // string | number
原理说明
- 对于
typeof v1,其类型为{},不包含明确的a属性,因此进入第二个分支,返回自定义标记类型,代表该类型参数是从约束范围 fallback 而来; - 对于
typeof v2,其类型明确包含a: string | number属性,因此匹配第一个分支,推导出实际的类型参数值。
如果不需要自定义标记,也可以返回never来区分,根据实际需求调整即可。
内容的提问来源于stack exchange,提问作者Stefan
相关产品推荐
相关产品推荐

