为何带计算属性键的映射对象函数无法正确推断类型?
TypeScript内联计算属性键的类型推断异常问题
问题背景
我需要将对象的字符串字面量键重新映射为格式稍有不同的字符串字面量键,以此得到目标对象。使用TypeScript 4.9.5版本的模板字符串字面量实现这一需求,同时将原对象的值类型映射为新对象中函数的参数类型(为清晰起见,也将其设为返回类型)。但奇怪的是,当使用内联表达式作为计算属性键时,类型推断会出现异常。
正常工作的代码示例
type Original = { foo: 'expects a string literal', baz: boolean, bar: number } type Mapped = { [prop in keyof Original as `$(${prop & string})`]: (arg: Original[prop]) => Original[prop] } type PropSelector<name extends string> = `$(${name & string})` const propSelector = <propName extends string>(propName: propName): PropSelector<propName> => `$(${propName})` const barKey = propSelector('bar'); const workingTestObject: Mapped = { '$(foo)': (arg) => 'expects a string literal', '$(baz)': (arg) => true, // 作为常量使用时完全正常(非内联) [barKey]: (arg) => 51345 } const correctFailures: Mapped = { // 返回类型错误时也能正确报错 // Type 'number' not assignable to 'expects a string literal' '$(foo)': (arg) => 5552, // Type 'string' not assignable to 'boolean' '$(baz)': (arg) => '1234', // Type 'boolean' not assignable to type 'number' [barKey]: (arg) => true }
上述代码中,barKey是propSelector函数调用的结果,输出为'$(bar)'且为字面量返回类型。将该常量作为对象键使用时,类型推断完全符合预期,返回类型错误也能被正确检测。
内联表达式导致类型推断失效的代码示例
const failingTestObject: Mapped = { '$(foo)': (arg) => 'expects a string literal', '$(baz)': (arg) => true, // 类型检查错误:`arg`被隐式推断为`any`?但返回类型推断正常? [propSelector('bar')]: (arg) => 13451 } // 使用propSelector时返回类型能正确报错 // 但无法推断arg的类型,因此会抛出"implicit any"错误 const correctFailures: Mapped = { // 返回类型应为字符串字面量,实际为number [propSelector('foo')]: (arg) => 5552, // 返回类型应为boolean,实际为string [propSelector('baz')]: (arg) => '1234', // 返回类型应为number,实际为boolean [propSelector('bar')]: (arg) => true }
直接将propSelector函数调用内联作为计算属性键时,TypeScript会将函数参数arg默认为any,但返回类型的推断和检查依然正常。
疑问与尝试
我已明确指定了propSelector函数的返回字面量类型,字符串键或引用常量键时类型推断正确,但内联表达式时失效。尝试调整字面量类型中的& string组合方式,行为没有变化。
我想知道:
- 这是什么原因导致的?
- 是否属于TypeScript的预期行为?
我希望尽可能自动化类型获取以避免重复编写代码,内联表达式对我的使用场景很重要,仅使用常量并不是理想方案。
后续修复
编辑:发现已有修复该问题的PR,且在发布本文几天后已合并!
内容的提问来源于stack exchange,提问作者Nicholas Kircher
相关产品推荐
相关产品推荐

