TypeScript类型映射中keyof推导异常的原因排查
问题原因与解决方法
核心问题
你这里的核心错误是EnumTypes的定义方向搞反了:你在里面存的是枚举值的联合类型(MyEnum是1|2,MyEnum2是'a'|'b'),但keyof作用在数字、字符串这类原始类型上时,TypeScript会返回其包装对象的内置方法名(比如数字的toString、toFixed,字符串的charAt等),这就是你看到那些奇怪键的原因。
你真正需要关联的不是枚举值类型,而是枚举对象的类型(也就是typeof MyEnum和typeof MyEnum2),只有枚举对象的类型才包含你自定义的键(AAA/BBB、a/b)。
修正后的代码
先修正EnumTypes的定义,让它映射到枚举对象的类型:
type MyEnum = 1 | 2 ; const MyEnum = { AAA: 1 as MyEnum, BBB: 2 as MyEnum, } type MyEnum2 = 'a' | 'b' ; const MyEnum2 = { a: 'a' as MyEnum2, b: 'b' as MyEnum2, } // 修正:这里存储枚举对象的类型(typeof 枚举对象) type EnumTypes = { myenum: typeof MyEnum; myenum2: typeof MyEnum2; } // 此时B的类型会自动对应枚举对象的合法键 function getB<E extends keyof EnumTypes, B extends keyof EnumTypes[E]>(e: E, key: B) { console.log(e, key); } // 现在类型检查完全正常 getB("myenum", "AAA"); // 合法 getB("myenum", "BBB"); // 合法 getB("myenum2", "a"); // 合法 getB("myenum", "a"); // 类型报错(符合预期)
补充说明
你之前的重载写法之所以能工作,是因为直接指定了B extends keyof typeof MyEnum——明确取的是枚举对象的键类型,而非枚举值类型。修正后的通用写法和重载效果一致,但更灵活,新增枚举时不需要额外添加重载声明。
内容的提问来源于stack exchange,提问作者Jan
相关产品推荐
相关产品推荐

