如何用TypeScript泛型强制嵌套对象内部属性类型一致?
问题:实现内层属性类型统一的嵌套对象泛型定义
需求
通过泛型类型实现一个对象记录,其中每个内层对象的所有属性必须为同一类型,不同内层对象的属性类型无需一致,仅需各自内部类型统一。
尝试实现的代码
// 确保所有属性都是T类型 type NestedObject<T> = { [K: string]: T; }; // 期望遍历未知类型的记录,返回每个属性都是对应类型对象的类型(当前实现不生效) type OuterObject<T extends Record<string, unknown>> = { [K: string]: NestedObject<T[keyof T]>; }; const validExample: OuterObject<{ pets: string; friendsAges: number; }> = { pets: { dog: "awesome", cat: "so great", dragon: "scary", }, friendsAges: { molly: 29, manuel: 44, }, }; const invalidExample: OuterObject<{ pets: string; friendsAges: number; }> = { pets: { dog: "awesome", cat: "so great", dragon: "scary", }, friendsAges: { molly: 29, manuel: "fourty-four", // 这里应该触发类型错误,但当前实现不会 buddy: [40] // ^ 只有传入联合类型外的类型才会报错:Type 'string[]' is not assignable to type 'string | number' }, };
当前问题
当前实现的OuterObject会将每个内层对象的属性类型设为泛型传入类型的所有值类型的联合(如string | number),导致内层对象中混合指定的类型不会触发错误(比如friendsAges中放入string不会报错),仅当传入联合类型外的类型(如数组)时才会报错,不符合需求。
解决方案
修改OuterObject为映射类型,针对传入泛型的每个键,绑定对应的值类型,确保每个内层对象的属性严格匹配原类型中该键指定的类型:
// 确保所有属性都是T类型 type NestedObject<T> = { [K: string]: T; }; // 正确的映射类型:遍历T的每个键K,对应内层对象的属性类型为T[K] type OuterObject<T extends Record<string, unknown>> = { [K in keyof T]: NestedObject<T[K]>; }; const validExample: OuterObject<{ pets: string; friendsAges: number; }> = { pets: { dog: "awesome", cat: "so great", dragon: "scary", }, friendsAges: { molly: 29, manuel: 44, }, }; const invalidExample: OuterObject<{ pets: string; friendsAges: number; }> = { pets: { dog: "awesome", cat: "so great", dragon: "scary", }, friendsAges: { molly: 29, manuel: "fourty-four", // ✅ 现在会触发类型错误:Type 'string' is not assignable to type 'number' buddy: [40] // ✅ 同样触发类型错误:Type 'number[]' is not assignable to type 'number' }, };
说明
这里使用了TypeScript的映射特性[K in keyof T],遍历传入泛型T的每个键K,将外层对象的K键对应的值类型设置为NestedObject<T[K]>——也就是该键在原类型中指定的类型的嵌套对象。这样每个内层对象的所有属性都会严格对应原类型中定义的类型,不会出现混合类型的情况,完美满足需求。
内容的提问来源于stack exchange,提问作者lentil-soup
相关产品推荐
相关产品推荐

