You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在TypeScript中定义含预定义属性与任意类型属性的映射类型?

解决方案

你可以用映射类型排除$id键来实现这个需求,具体写法如下:

type Foo = {
  $id: string;
} & {
  [K in string as Exclude<K, '$id'>]: number;
};

或者更简洁的写法,结合Record和Exclude:

type Foo = { $id: string } & Record<Exclude<string, '$id'>, number>;

这样定义后,Foo类型的对象必须包含$id字符串属性,其他任意字符串键对应的属性都得是数值类型,完全符合你的要求:

const foo: Foo = {
  $id: 'id',
  bar: 123,
  baz: 456 // 合法
};

const invalidFoo: Foo = {
  $id: 123, // 报错:$id必须是字符串类型
  bar: 'abc' // 报错:bar必须是数值类型
};

为啥之前的写法不行?

第一种写法的问题

type Foo = {
  $id: string;
  [key: string]: number;
}

这里的索引签名[key: string]: number是对所有字符串键属性的强制约束,要求所有属性都得是number,但$id是string类型,直接和索引签名冲突,TypeScript肯定会报错。

第二种写法的问题

type Foo = {
  [key: string]: number;
} & { $id: string };

这种交叉类型看似合理,但实际访问foo.$id时,TypeScript会把它解析成number & string,也就是never类型——毕竟一个值不可能既是字符串又是数字,这就导致$id属性根本没法正常用,完全不符合预期。


内容的提问来源于stack exchange,提问作者Lehks

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 05:24:26