泛型参数继承对象时,T['x']索引类型为何触发TS编译错误?
为什么TypeScript泛型中
{[k in T['x']]: number}无法赋值{abc:1}? 先看你给出的代码:
type S = {x: 'abc'} function f<T extends S>() { const x: {[k in T['x']]: number} = {abc: 1} // error const y: {[k in S['x']]: number} = {abc: 1} } function f1<T extends S>() { const x: T['x'] = 'abc' const y: T['x'] = 'haha' // error }
对应的编译错误:
- Type '{ abc: number; }' is not assignable to type '{ [k in T["x"]]: number; }'.
Object literal may only specify known properties, and 'abc' does not exist in type '{ [k in T["x"]]: number; }'.
问题原因
核心在于泛型类型的延迟解析机制:
- 当定义泛型函数
f<T extends S>时,T是未具体化的类型参数。尽管T['x']被约束为'abc',但在函数定义阶段,TypeScript不会直接将T['x']解析为具体的字面量'abc',而是将其视为一个受约束的类型变量。 - 映射类型
{[k in T['x']]: number}是依赖泛型参数的动态类型,此时TypeScript无法确定T['x']的具体值(哪怕逻辑上它只能是'abc'),因此会认为{abc: 1}这个具体对象的键'abc'可能不属于T['x']对应的键类型,从而抛出错误。 - 而
S['x']是明确的字面量类型'abc',所以{[k in S['x']]: number}会被直接解析为{abc: number},赋值自然符合要求。 - 函数
f1的逻辑是正常的:T['x']被约束为'abc','haha'不符合约束所以报错,'abc'符合约束则通过检查。
解决方法
如果需要在泛型函数中使用这个映射类型,可以选择以下两种方式:
- 使用类型断言绕过检查:
const x: {[k in T['x']]: number} = {abc: 1} as {[k in T['x']]: number};
- 如果业务逻辑不依赖
T的具体类型,直接使用S['x']代替T['x']:
const x: {[k in S['x']]: number} = {abc: 1};
内容的提问来源于stack exchange,提问作者user17418101
相关产品推荐
相关产品推荐

