如何在TypeScript中使指定嵌套子属性变为必填项?
如何在TypeScript中使指定嵌套子属性变为必填项?
嘿,我来帮你搞定这个TypeScript类型定义的问题!咱们先从现有的接口定义说起:
interface Vegetable { vitamins?: string; foo?: string; } interface Fruit { seeds?: number; bar?: string; } interface Meat { flesh?: string; } interface Food { vegetable?: Vegetable; fruit?: Fruit; meat?: Meat; }
你的需求是创建一个FoodWithSomeRequiredFields接口,要求:
vegetable和fruit是必填的,而且它们内部的所有属性也要变成必填meat保持可选,内部的flesh也依然可选
你之前尝试用Required<Pick<Food, "vegetable" | "fruit">>,这个只能让第一层的vegetable和fruit变成必填,但它们内部的子属性还是可选的,这就是为什么vitamins: undefined不会报错的原因。
解决方法:交叉类型+Required工具类型
我们可以用交叉类型结合Required工具类型,精准控制需要必填的嵌套属性:
type FoodWithSomeRequiredFields = Omit<Food, "vegetable" | "fruit"> & { vegetable: Required<Vegetable>; fruit: Required<Fruit>; };
代码解释:
Omit<Food, "vegetable" | "fruit">:保留Food接口中除了vegetable和fruit之外的其他属性(也就是meat),保持它原来的可选状态。& { vegetable: Required<Vegetable>; fruit: Required<Fruit>; }:交叉一个新的类型,把vegetable和fruit设为必填,同时用Required<Vegetable>把Vegetable的所有可选属性转为必填,fruit同理。
测试验证:
现在咱们来验证这个类型是否符合需求:
1. 第一层属性必填验证
当你把vegetable设为undefined时,TypeScript会抛出错误,符合预期:
const foodValidError: FoodWithSomeRequiredFields = { vegetable: undefined, // ✅ 报错:Type 'undefined' is not assignable to type 'Required<Vegetable>'. fruit: { seeds: 1, bar: "s", }, };
2. 嵌套子属性必填验证
当你在vegetable里省略vitamins或者设为undefined时,也会报错,这正是我们想要的:
const foodInvalid1: FoodWithSomeRequiredFields = { vegetable: { vitamins: undefined, // ✅ 报错:Type 'undefined' is not assignable to type 'string'. }, fruit: { seeds: 1, bar: "s", }, };
3. 保持meat的可选状态
meat依然是可选的,内部的flesh也可以不填,完全符合需求:
const foodValid: FoodWithSomeRequiredFields = { vegetable: { vitamins: "A", foo: "carrot", }, fruit: { seeds: 5, bar: "orange", }, // meat可以不填,或者只填部分属性 meat: { flesh: "chicken" } };
这样就完美实现了你想要的类型定义啦!
备注:内容来源于stack exchange,提问作者Remi
相关产品推荐
相关产品推荐

