如何为嵌套对象索引的取值函数编写正确TypeScript类型?
问题描述
我有一个包含固定属性的对象,其中custom属性的字段是父对象属性的子集,类型定义如下:
interface TFruit { weight: number; color: string; shape: 'round' | 'long' | 'oblong' custom: TCustom } interface TCustom { weight?: number; color?: string; }
我需要实现一个函数:当custom中的属性值不为undefined时,优先取该值;否则取父对象的对应属性值。同时希望TypeScript能根据传入的属性,自动推断出返回值的精确类型。
我尝试的实现代码如下:
const getProperty = <TProperty extends keyof TCustom>( fruit: TFruit, property: TProperty ): TFruit['custom'][TProperty] extends undefined ? TFruit[TProperty] : TFruit['custom'][TProperty] => { const customProperty = fruit['custom'][property]; if (customProperty !== undefined) { return customProperty; } return fruit[property]; }
但出现了以下类型错误:
Type 'TCustom[TProperty] & {}' is not assignable to type 'TCustom[TProperty] extends undefined ? TFruit[TProperty] : TFruit['custom'][TProperty]'.ts(2322)
解决方案
你之前的条件类型写法存在逻辑问题:TFruit['custom'][TProperty]的类型是number | undefined或string | undefined,它并不完全继承undefined,导致条件类型的结果与实际返回值类型不匹配。
正确的做法是直接将返回值类型定义为TFruit[TProperty]——因为custom的属性类型本身就是父对象对应属性的可选版本,非undefined时类型与父对象完全一致,最终返回值必然符合父对象的属性类型。同时可以用??操作符简化逻辑,让TypeScript自动识别类型:
const getProperty = <TProperty extends keyof TCustom>( fruit: TFruit, property: TProperty ): TFruit[TProperty] => { return fruit.custom[property] ?? fruit[property]; };
类型验证示例
const apple: TFruit = { weight: 100, color: 'red', shape: 'round', custom: { weight: 120 } }; // 类型推断为 number const appleWeight = getProperty(apple, 'weight'); // 类型推断为 string const appleColor = getProperty(apple, 'color');
这样既满足了业务逻辑需求,又让TypeScript能准确推断返回值的精确类型。
内容的提问来源于stack exchange,提问作者thecartesianman
相关产品推荐
相关产品推荐

