TypeScript:能否排除Record类型特定字面量?如何定义含动态属性的对象?
问题解答
一、能否从Record类型中排除特定的标签字面量?
可以,直接用TypeScript内置的Omit工具类型就能实现。比如要从Record<string, string>里排除'id'这个键,写法如下:
type RecordWithoutId = Omit<Record<string, string>, 'id'>;
这个类型代表:所有字符串类型的键(除了'id')对应的值都是string类型。
二、如何声明包含动态属性+指定类型id的对象类型?
你尝试的两种写法都有问题:
- 第一种写法里,
[key: string]: string是全局索引签名,要求所有字符串键的值都是string,但id: number违背了这个规则,TypeScript会直接报错; - 第二种交叉类型写法中,
id的类型会被解析为string & number(即never类型),完全不符合需求。
正确的做法是把索引签名限定为除了id之外的字符串键,有两种等价实现方式:
方案一:映射类型 + Exclude
type SomeType = { id: number; } & { [key in Exclude<string, 'id'>]: string; };
方案二:Omit + Record 交叉
type SomeType = { id: number } & Omit<Record<string, string>, 'id'>;
这两种写法的效果完全一致:id属性固定为number类型,其他任意字符串键的属性必须是string类型。测试示例:
const validObj: SomeType = { id: 1001, username: 'maja', email: 'maja@example.com' }; const invalidObj: SomeType = { id: '1001', // 报错:类型"string"不能赋值给类型"number" username: 123 // 报错:类型"number"不能赋值给类型"string" };
内容的提问来源于stack exchange,提问作者maja
相关产品推荐
相关产品推荐

