TypeScript中如何定义与兼容接口协变的只读Record类型
方案1:泛型约束实现
直接在序列化方法上增加泛型约束,要求传入对象的所有键都是string类型:
// 定义约束工具类型:仅键全为string的对象可通过校验 type StringKeyOnly<T> = keyof T extends string ? T : never // 序列化方法定义 function serialize<T>(obj: StringKeyOnly<T>) { // 你的序列化逻辑 }
使用测试:
interface Foo { foo: number, bar: string } const foo: Foo = { foo: 1, bar: 'test' } serialize(foo) // 正常通过校验 const objWithNumberKey = { 1: 'a', 2: 'b' } serialize(objWithNumberKey) // 类型报错,符合预期
这个方案的优势是可以保留传入对象的原始类型信息,方便在序列化逻辑内部做类型推导和处理。
方案2:协变只读Record实现
按照你提到的不可变类型协变的思路,定义只读的Record类型即可兼容所有带string键的接口:
// 定义协变的只读Record类型 type ReadOnlyRecord<K extends string | number | symbol, V> = { readonly [P in K]: V } // 序列化方法定义 function serialize(obj: ReadOnlyRecord<string, unknown>) { // 你的序列化逻辑 }
使用测试:
interface Foo { foo: number, bar: string } const foo: Foo = { foo: 1, bar: 'test' } serialize(foo) // 正常通过校验,不存在可变Record的不变性冲突问题
原理是TypeScript中只读属性的类型是协变的,和不可变列表支持协变的逻辑完全一致,只要对象的键都是string类型、值是unknown的子类型,就可以正常赋值给ReadOnlyRecord<string, unknown>。
内容的提问来源于stack exchange,提问作者fortran
相关产品推荐
相关产品推荐

