TypeScript泛型extends never:DeepReadonly处理字面量类型的疑问
关于Type Challenges Deep Readonly热门解法的疑问
Type Challenges的Deep Readonly挑战有一个热门解法:
type DeepReadonly<T> = keyof T extends never ? T : { readonly [k in keyof T]: DeepReadonly<T[k]> }; // 示例 type DeepResult = DeepReadonly<{ hello: 'world' }> // ^? type DeepResult = { readonly hello: 'world'; }
我知道这个解法存在缺陷,但搞不懂它处理简单场景的逻辑:
type DeepResult2 = DeepReadonly<'world'>; // ^? type DeepResult2 = "world"
我的疑问是:keyof 'world' extends never为什么成立,从而直接返回原类型T(也就是'world'),而不是走映射类型分支?
解答
要弄明白这个问题,得先搞清楚keyof对原始类型的作用:
- 在TypeScript中,
keyof操作符针对对象类型会返回它的键组成的联合类型,但对于原始类型(比如字符串、数字、布尔值这些),情况不一样。 - 对于字面量原始类型(比如
'world'这种具体的字符串),keyof 'world'的结果是never。因为这类字面量类型本身没有可被keyof提取的枚举键(注意:原始值作为对象访问时的属性,比如'world'.length里的length,属于对应的包装对象类型String的键,而非字面量类型'world'的键)。 - 既然
keyof 'world'本身就是never,那keyof 'world' extends never这个判断自然成立,所以会触发条件分支里直接返回原类型'world'的逻辑。
简单来说:字面量原始类型没有可被keyof识别的键,所以keyof结果为never,从而走了返回原类型的分支。
内容的提问来源于stack exchange,提问作者stratis
相关产品推荐
相关产品推荐

