TypeScript国家-州联动类型定义报错原因及修复方案
错误原因与修复方案:Type 'number' cannot be used to index type 'T[keyof T]'
错误原因
你遇到的问题核心在于泛型对联合类型的处理逻辑:
- 定义
CountryStateType<T extends CountriesType>时,T[keyof T]是T所有属性值的联合类型(这里就是readonly ['Vienna', 'Raiding'] | readonly ['Berlin'])。 - TypeScript在泛型定义阶段,无法确保这个联合类型的每一个成员都支持
number索引——虽然实际你的属性值都是数组,但泛型层面只会识别它是T属性值的联合,不会做具体类型的推断,因此抛出索引错误。 - 另外原写法还有隐藏的类型安全问题:生成的类型是
['Austria' | 'Germany', 'Vienna' | 'Raiding' | 'Berlin'],允许不匹配的组合(比如['Austria', 'Berlin']),不符合你想要的「国家对应专属州」的逻辑。
修复方法
要解决这个问题,需要让国家和对应的州严格绑定,同时绕过联合类型的索引限制。可以用映射类型生成每个国家与对应州的元组,再取这些元组的联合类型:
const AUSTRIA = ['Vienna', 'Raiding'] as const; const GERMANY = ['Berlin'] as const; const testCountries = { Austria: AUSTRIA, Germany: GERMANY } as const; type CountriesType = typeof testCountries; // 修复后的类型定义 type CountryStateType<T extends CountriesType> = { [K in keyof T]: [K, T[K][number]] }[keyof T]; // 正确使用示例 const validPair1: CountryStateType<CountriesType> = ['Austria', 'Raiding']; // 正常 const validPair2: CountryStateType<CountriesType> = ['Germany', 'Berlin']; // 正常 // const invalidPair: CountryStateType<CountriesType> = ['Austria', 'Berlin']; // 报错,类型不匹配
修复原理
- 映射类型
{ [K in keyof T]: [K, T[K][number]] }会遍历T的每个键K,生成对应的元组类型:比如对Austria生成['Austria', 'Vienna' | 'Raiding'],对Germany生成['Germany', 'Berlin']。 - 最后通过
[keyof T]取映射类型的所有值的联合,得到的是严格绑定国家与对应州的元组联合类型,既解决了索引错误,又保证了类型安全。
为什么单独获取某国的州类型正常?
当你写CountriesType['Austria'][number]时,CountriesType['Austria']是具体的数组类型readonly ['Vienna', 'Raiding'],不是联合类型,TypeScript明确知道它支持number索引,所以不会报错。
内容的提问来源于stack exchange,提问作者nikitimi
相关产品推荐
相关产品推荐

