You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.20 01:03:18