如何避免Record工具类型使用模板字面量类型时被转为string类型
根因说明
TypeScript 中使用模板字面量类型作为 Record 的键类型时,编译器会自动将模板字面量类型拓宽为基础的 string 类型,索引签名不会对键的字面量格式做校验,因此不符合格式的键不会触发报错。
解决方案
可以通过泛型函数+键校验工具类型的方案实现精确约束,原理是通过泛型精确捕获对象所有键的字面量类型,再逐个校验键是否符合模板格式要求,避免类型拓宽:
type Dunder = `__${string}__`; // 键校验工具类型:遍历对象所有键,不符合Dunder格式的键会被标记为never触发报错 type ValidateDunderObj<T> = { [K in keyof T]: K extends Dunder ? T[K] : never } // 泛型构造函数:用于创建符合约束的Dunder对象 const defineDunderObj = <T extends Record<Dunder, unknown>>(obj: ValidateDunderObj<T>) => obj
使用示例
// 符合约束的对象,无编译报错 const validExample = defineDunderObj({ __fieldA__: '', __fieldB__: 123 }) // 不符合约束的对象,fieldB处会触发编译报错 const invalidExample = defineDunderObj({ __fieldA__: '', fieldB: '' // 编译器提示:类型"fieldB"不可分配给类型`__${string}__` })
如果使用 TypeScript 4.9 及以上版本,也可以配合 satisfies 运算符实现更简洁的校验:
const example = { __fieldA__: '', fieldB: '' } satisfies Record<Dunder, unknown> // fieldB处会直接触发编译报错
内容的提问来源于stack exchange,提问作者Brad Turner
相关产品推荐
相关产品推荐

