TypeScript 4.4 introduced在index signatures中使用pattern或placeholder的能力template literal types(如microsoft/TypeScript#40598中实现的).但`person${AllowedIndex}Name`
不是模式模板文字类型.事实上,它甚至不是一个模板文字类型,因为它被TypeScriptEager 地判断为字符串literal types和"person1Name" | "person2Name" | "person3Name" | "person4Name" | "person5Name"
的union. 而且不能在索引签名中使用字符串文字类型的联合.
相反,您可以使用mapped types来创建一个对象类型,其键是字符串字面量的联合. 如果您希望这些密钥是必需的,则看起来像{[K in `person${AllowedIndex}Name`]: string}
,如果您希望它们是可选的,则看起来像{[K in `person${AllowedIndex}Name`]?: string}
.同样,你可以使用Partial
和Record
实用程序类型的组合,如Partial<Record<`person${AllowedIndex}Name`, string>>
.
请注意,映射类型是它们自己的类型,不能向它们添加属性.如果你想组合几个映射类型,你可以使用intersection. 或者,如果你想以interface结束,你可以使用interface extension来组合父映射类型(但只能通过一个命名类型,如Partial
或Record
)和你添加的属性.这给
type AllowedIndex = 1 | 2 | 3 | 4 | 5;
interface Foo extends
Partial<Record<`person${AllowedIndex}Name`, string>>,
Partial<Record<`person${AllowedIndex}Address`, string>> {
category: string;
department: string;
}
你可以判断它以确保它的行为符合要求:
type ExpandedFoo = {[K in keyof Foo]: Foo[K]};
/* type ExpandedFoo = {
category: string;
department: string;
person1Name?: string | undefined;
person2Name?: string | undefined;
person3Name?: string | undefined;
person4Name?: string | undefined;
person5Name?: string | undefined;
person1Address?: string | undefined;
person2Address?: string | undefined;
person3Address?: string | undefined;
person4Address?: string | undefined;
person5Address?: string | undefined;
} */
Playground link to code