TypeScript类型条件属性实现:食谱配料类型约束需求
实现RecipeIngredient的类型约束
当然可以实现这个精准的类型约束!你需要利用TypeScript的**联合类型(Union Types)**来拆分不同场景,强制要求:只有当measurement为"custom"时,quantity才允许是字符串类型;其他情况下quantity必须是数字类型。
核心解决方案代码
// 拆分两种场景的联合类型 type RecipeIngredient = // 非custom场景:measurement为grams/mililitres时,quantity必须是number | { name: string; quantity: number; measurement: "grams" | "mililitres" } // custom场景:measurement为custom时,quantity允许是string | { name: string; quantity: string; measurement: "custom" };
如果希望custom场景下quantity既可以是字符串也可以是数字(比如允许quantity: 2搭配measurement: "custom"),可以调整第二个分支的类型:
type RecipeIngredient = | { name: string; quantity: number; measurement: "grams" | "mililitres" } | { name: string; quantity: number | string; measurement: "custom" };
合法示例验证
以下写法都会通过TypeScript的类型检查:
// 标准重量配料(grams + number) const potatoes: RecipeIngredient = { name: 'potatoes', quantity: 100, measurement: 'grams' }; // 标准体积配料(mililitres + number) const milk: RecipeIngredient = { name: 'milk', quantity: 200, measurement: 'mililitres' }; // 自定义数量配料(custom + string) const rosemary: RecipeIngredient = { name: 'rosemary', quantity: 'a handful', measurement: 'custom' };
非法示例(会触发类型报错)
这些写法会被TypeScript拦截,完全符合你的约束需求:
// ❌ 错误:measurement为grams时,quantity不能是string const fish: RecipeIngredient = { name: 'fish', quantity: '100g', measurement: 'grams' }; // ❌ 错误:measurement为mililitres时,quantity不能是string const juice: RecipeIngredient = { name: 'juice', quantity: '一杯', measurement: 'mililitres' };
额外优势:自动类型窄化
使用这个联合类型后,TypeScript会在代码中自动进行类型推断。比如当你判断measurement的值时,它会自动识别quantity的类型:
function printIngredient(ingredient: RecipeIngredient) { if (ingredient.measurement === 'custom') { // 这里TypeScript明确知道quantity是string(或number|string,取决于你的定义) console.log(`- ${ingredient.name}: ${ingredient.quantity}`); } else { // 这里TypeScript明确知道quantity是number console.log(`- ${ingredient.name}: ${ingredient.quantity} ${ingredient.measurement}`); } }
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

