TypeScript中如何定义含指定类型固定键、其余属性为统一类型的Record
问题核心原因
你尝试的两种写法报错,本质是TypeScript的索引签名规则限制:所有明确声明的属性类型必须是索引签名返回类型的子类型,foo:string和索引签名string:number存在类型冲突,因此直接交叉或者写在同一个接口里都会触发类型错误。
最优惯用解决方案:泛型校验函数
这是目前社区最通用的简洁实现,不需要提前声明所有属性名,会自动推导校验所有输入字段:
// 定义通用校验函数 const defineSpecialObject = <T extends { foo: string } & Record<Exclude<keyof T, 'foo'>, number>>(obj: T) => obj // 直接使用,不需要手动写类型注解 const x = defineSpecialObject({ foo: "foo", bar: 3, // test: "abc" // 此行会报错,非foo字段必须为number类型 })
原理是通过泛型T捕获实际传入的对象结构,再用Exclude<keyof T, 'foo'>把foo属性排除,要求剩下所有属性的类型都是number,完全满足需求。
可选方案:预定义属性名的通用类型
如果你提前知道除了foo之外还有哪些属性,可以直接定义通用工具类型使用:
type SpecialObject<ExtraKeys extends string = never> = { foo: string } & Record<Exclude<ExtraKeys, 'foo'>, number> // 使用时传入额外属性的名称作为泛型参数 const x: SpecialObject<'bar' | 'baz'> = { foo: "foo", bar: 3, baz: 4 }
内容的提问来源于stack exchange,提问作者sam256
相关产品推荐
相关产品推荐

