TypeScript参数组合约束问题:索引类型报错原因咨询
TypeScript泛型分支中的索引类型错误解析
先看你提供的代码:
enum ParamOneType { Round, Square, } interface PossibleValues { [ParamOneType.Round]: 'a' | 'b'; [ParamOneType.Square]: 'c' | 'd'; } const indexRound = { a: 'whatever', b: 'whatever', }; const doSomething = <T extends ParamOneType>( paramOne: T, paramTwo: PossibleValues[T], ): void => { switch (paramOne) { case ParamOneType.Round: { // Type 'PossibleValues[T]' cannot be used to index type '{ a: string; b: string; }' const b = indexRound[paramTwo]; } } };
问题原因
虽然调用doSomething(ParamOneType.Round, 'a')时,VS Code能正确识别出此时paramTwo的类型是"a" | "b",但在函数内部的switch分支里,TypeScript没办法把泛型T自动收窄到ParamOneType.Round。
泛型T的约束是extends ParamOneType,这意味着T可以是ParamOneType的任意成员(甚至是Round | Square的联合类型)。编译器在函数内部无法确定调用时T的具体值,所以PossibleValues[T]的类型仍然是'a'|'b'|'c'|'d'的联合,而indexRound只接受'a'|'b'作为合法索引,两者类型不匹配,因此报错。
解决方法
方法1:类型断言
直接将paramTwo断言为indexRound的合法键类型:
case ParamOneType.Round: { const b = indexRound[paramTwo as keyof typeof indexRound]; }
方法2:手动缩小类型范围
在分支里添加类型守卫,明确paramTwo的类型属于indexRound的键:
case ParamOneType.Round: { if (['a', 'b'].includes(paramTwo as string)) { const b = indexRound[paramTwo as keyof typeof indexRound]; } break; }
方法3:重构类型关联
让类型系统能自动推断出对应关系,比如将索引对象和类型绑定:
const indexMap = { [ParamOneType.Round]: { a: 'whatever', b: 'whatever' }, [ParamOneType.Square]: { c: 'whatever', d: 'whatever' }, } as const; type PossibleValues = { [K in keyof typeof indexMap]: keyof typeof indexMap[K]; }; const doSomething = <T extends ParamOneType>( paramOne: T, paramTwo: PossibleValues[T], ): void => { const b = indexMap[paramOne][paramTwo]; };
内容的提问来源于stack exchange,提问作者Thijs
相关产品推荐
相关产品推荐

