TypeScript类型收窄:约束分组数组内对象的category类型一致
如何定义按category分组且同组内category一致的TypeScript对象类型
你的需求是让对象中每个数组内的Machine实例的category完全一致,原类型因为category是宽泛的string类型,无法实现这个约束。以下是两种可行的解决方案:
方案1:泛型Machine类型+工具函数(推荐,灵活支持任意category)
首先定义带泛型的Machine类型,让category绑定到具体的字符串字面量类型:
type Machine<C extends string> = { category: C; serial: string; };
接着创建一个工具函数,用来约束每个数组内的category必须统一,同时让TypeScript自动推断每个数组的category类型:
function createMachines<T extends { [key: number]: readonly Machine<string>[] }>( machines: { [K in keyof T]: T[K] extends readonly Machine<infer C>[] ? readonly Machine<C>[] : never } ): T { return machines; }
使用示例:
- 合法情况(同组category一致,无报错):
const machines = createMachines({ 1: [{ category: "core", serial: "110" }, { category: "core", serial: "231" }], 2: [{ category: "style", serial: "114" }, { category: "style", serial: "239" }] });
- 非法情况(同组category不一致,TypeScript会抛出错误):
const invalidMachines = createMachines({ 1: [{ category: "core", serial: "110" }, { category: "core", serial: "231" }], 2: [{ category: "style", serial: "114" }, { category: "core", serial: "239" }] // 报错:类型"{ category: "core"; serial: "239"; }"的属性"category"与类型"Machine<"style">"的属性"category"不兼容 });
方案2:提前指定所有可能的category(适合已知固定category的场景)
如果你的category只有固定的几个值(比如"core"和"style"),可以直接定义联合类型来约束:
type Category = "core" | "style"; type Machine<C extends Category> = { category: C; serial: string; }; type IMachines = { [key: number]: Machine<"core">[] | Machine<"style">[]; };
使用时,TypeScript会自动检查每个数组内的category是否统一:
// 合法 const machines: IMachines = { 1: [{ category: "core", serial: "110" }, { category: "core", serial: "231" }], 2: [{ category: "style", serial: "114" }, { category: "style", serial: "239" }] }; // 非法,报错 const invalidMachines: IMachines = { 1: [{ category: "core", serial: "110" }, { category: "core", serial: "231" }], 2: [{ category: "style", serial: "114" }, { category: "core", serial: "239" }] };
原泛型尝试失败的原因
你之前的泛型定义让IMachines<T>的所有数组共享同一个T类型,导致所有数组的category必须完全相同,无法实现每个数组独立使用不同的category。上面的方案通过每个数组独立推断泛型参数(工具函数方案)或联合类型分支(固定category方案)解决了这个问题。
内容的提问来源于stack exchange,提问作者pepinillo6969
相关产品推荐
相关产品推荐

