如何为TypeScript任意键场景下的in操作符实现类型收窄?
问题解答
直接用in操作符没法对any类型的tag实现类型收窄,原因很简单:TypeScript里的any类型会完全绕过类型检查逻辑,不管你写什么条件判断,TypeScript都不会自动把any收窄成更具体的类型——它默认any可以是任何值,in操作符的判断不会改变这个推断结果。
要实现类型收窄,得先给TypeScript一个明确的类型范围参考,有两种常用方法:
方法1:自定义类型守卫函数
先给primitives的键定义明确的类型,再写一个类型守卫函数来判断tag是否属于这个键类型:
// 定义primitives的合法键类型 type PrimitiveTag = 'string' | 'number' | 'boolean'; // 给primitives指定类型 const primitives: Record<PrimitiveTag, unknown> = { string: '', number: 0, boolean: false }; // 自定义类型守卫,告诉TypeScript符合条件的tag是什么类型 function isPrimitiveTag(tag: any): tag is PrimitiveTag { return tag in primitives; } function dostuff(tag: any) { if (isPrimitiveTag(tag)) { // 这里tag的类型会被收窄为PrimitiveTag return primitives[tag]; } // ... }
方法2:替换any为联合类型
把tag的类型从纯粹的any改成「目标键类型 + any」的联合类型,让TypeScript能识别可收窄的范围:
type PrimitiveTag = 'string' | 'number' | 'boolean'; const primitives: Record<PrimitiveTag, unknown> = { string: '', number: 0, boolean: false }; function dostuff(tag: PrimitiveTag | any) { if (tag in primitives) { // 这里tag会被自动收窄为PrimitiveTag return primitives[tag]; } // ... }
核心逻辑就是:不能让tag的类型是无边界的any,必须给TypeScript一个可参考的类型集合,不管是通过类型守卫手动约束,还是用联合类型划定范围,in操作符才能正常发挥类型收窄的作用。
内容的提问来源于stack exchange,提问作者user29889977
相关产品推荐
相关产品推荐

