TypeScript无法正确推断类型化字符串变量类型的问题及解决办法问询
解决方法
你的问题出在TypeScript无法确定animalPlural对应的属性是数组类型还是布尔类型。keyof Animals['animals'][typeof animal]包含了两个可能的键:复数数组(如cats/dogs)和allSelected(布尔值),因此TypeScript会认为allAnimals.animals[animal][animalPlural]可能是布尔值,而布尔值没有selected属性,导致报错。
可以通过泛型约束明确类型关联,让TypeScript知道animal和对应的复数数组、状态类型之间的映射关系:
interface CatState { name: string, selected: boolean, color: string, height: number } interface DogState{ name: string, selected: boolean, race: string, age: number, eyeColor: string } export interface Animals { animals: { cat: { cats: CatState[], allSelected: boolean, }, dog: { dogs: DogState[], allSelected: boolean, }, } }; // 定义动物类型、对应的复数属性、状态类型的映射 type AnimalKey = keyof Animals['animals']; type AnimalPlural<T extends AnimalKey> = T extends 'cat' ? 'cats' : 'dogs'; type AnimalState<T extends AnimalKey> = T extends 'cat' ? CatState : DogState; const selectAnimal = <T extends AnimalKey>(allAnimals: Animals, animal: T, index: number) => { // 明确animalPlural是对应复数数组的键 const animalPlural = `${animal}s` as AnimalPlural<T>; // 获取对应数组并指定状态类型 const targetArray = allAnimals.animals[animal][animalPlural] as AnimalState<T>[]; targetArray[index].selected = true; };
修改后,TypeScript能准确推断出targetArray[index]的类型是CatState或DogState,两者都包含selected属性,错误会消失。
如果想避免模板字符串的类型不确定性,也可以直接通过条件类型返回复数键:
const getAnimalPlural = <T extends AnimalKey>(animal: T): AnimalPlural<T> => { return animal === 'cat' ? 'cats' : 'dogs' as AnimalPlural<T>; }; // 在selectAnimal里使用: const animalPlural = getAnimalPlural(animal);
这种方式更安全,不会因模板字符串拼写错误导致类型问题。
内容的提问来源于stack exchange,提问作者four-eyes
相关产品推荐
相关产品推荐

