TypeScript中检查对象含指定键并取值的类型错误解决问询
解决TypeScript中
in操作符无法自动缩小联合索引类型的问题 你遇到的问题是TypeScript的常见限制:虽然food in FRUIT_COLORS能在运行时判断键是否存在,但TypeScript无法自动将联合类型Food缩小为FRUIT_COLORS的键类型,导致索引时出现类型错误。下面提供两种无需手动强制转换类型的解决方案:
方案一:自定义类型守卫函数
通过自定义类型守卫函数,让TypeScript明确识别in判断后的类型范围:
const FRUIT_COLORS = { apple: "red", orange: "orange", banana: "yellow" } as const; const VEGETABLE_COLORS = { carrot: "orange", broccoli: "green", asparagus: "green" } as const; type Fruit = keyof typeof FRUIT_COLORS; type Vegetable = keyof typeof VEGETABLE_COLORS; type Food = Fruit | Vegetable; // 自定义类型守卫,判断key是否属于目标对象的键类型 function isKeyOf<T extends object>(obj: T, key: unknown): key is keyof T { return key in obj; } export function color(food: Food) { if (isKeyOf(FRUIT_COLORS, food)) { return FRUIT_COLORS[food]; // 此处food类型自动缩小为Fruit } return VEGETABLE_COLORS[food]; // 此处food类型自动缩小为Vegetable }
这里用as const确保对象的键和值类型被精确推断,自定义的isKeyOf函数会告诉TypeScript:当判断为真时,food就是目标对象的键类型,从而消除索引错误。
方案二:合并对象后直接索引
如果业务允许,将两个颜色对象合并为一个,直接通过Food类型索引,这是最简洁的解决方式:
const FRUIT_COLORS = { apple: "red", orange: "orange", banana: "yellow" } as const; const VEGETABLE_COLORS = { carrot: "orange", broccoli: "green", asparagus: "green" } as const; // 合并两个对象并锁定类型 const FOOD_COLORS = { ...FRUIT_COLORS, ...VEGETABLE_COLORS } as const; type Food = keyof typeof FOOD_COLORS; export function color(food: Food) { return FOOD_COLORS[food]; // 类型完全匹配,无任何错误 }
这种方式去掉了分支判断,直接通过合并后的对象索引,TypeScript能准确推断返回值为所有颜色的联合类型,代码更简洁易维护。
内容的提问来源于stack exchange,提问作者LandonSchropp
相关产品推荐
相关产品推荐

