如何定义含固定属性与其他不同签名属性的TypeScript类型?
问题原因
你写的映射类型[K in string]本质是字符串索引签名,并非遍历具体的键联合类型。当判断K extends "foo"时,这里的K代表所有可能的字符串(string类型),而非单个键字面量,string extends "foo"的结果为false,最终整个类型等价于{ [key: string]: string[] },因此会错误要求foo也必须是string[]类型。
解决方案
以下几种写法都能实现需求:
方案一:交叉类型结合Omit
通过Omit排除索引类型中的foo,再与固定属性的类型交叉:
type Spec = { foo: string } & Omit<Record<string, string[]>, "foo">; const spec: Spec = { foo: 'a', bar: ['a'], baz: ['b'] };
方案二:映射类型的as子句(TypeScript 4.1+)
利用as子句明确分离foo和其他字符串键的类型定义:
type Spec = { [K in "foo"]: string; } & { [K in string as Exclude<K, "foo">]: string[]; }; const spec: Spec = { foo: 'a', bar: ['a'], baz: ['b'] };
方案三:类型推断简化写法
通过infer让TS自动处理类型合并的优先级:
type Spec = { foo: string; [key: string]: string[]; } extends infer T ? T : never; const spec: Spec = { foo: 'a', bar: ['a'], baz: ['b'] };
以上三种写法均能保证foo必须为string类型,其他任意字符串属性必须为string[]类型,同时支持新增任意符合要求的属性。
内容的提问来源于stack exchange,提问作者aiven715
相关产品推荐
相关产品推荐

