Typescript 接口,其中密钥名称具有已知前缀,但完整密钥未知

d-_*_*_-b 4 typescript

有没有一种方法可以定义一个接口,其中键具有已知前缀(added_, removed_)但完整键未知?

例如,一个有效的对象可能是:

{
   name: "",
   added_abc: [1,2,3],
   added_bcd: [2],
   removed_abcd: [4,5],
   removed_xyz: [],
}
Run Code Online (Sandbox Code Playgroud)

我想确保有一个接口:

interface myobject {
   name: string;
   added_*?: number[];
   removed_*?: number[];
}
Run Code Online (Sandbox Code Playgroud)

jca*_*alz 8

当 TypeScript 4.4 发布时,您将能够利用模板字符串模式文字索引签名,如microsoft/TypeScript#44512中实现的那样,然后这将起作用:

// TS4.4+
interface MyObject {
  name: string;
  [k: `added_${string}`]: number[];
  [k: `removed_${string}`]: number[];
}

const myObject: MyObject = {
  name: "",
  added_abc: [1, 2, 3],
  added_bcd: [2],
  removed_abcd: [4, 5],
  removed_xyz: [],
} // okay

const myBadObject: MyObject = {
  name: "",
  added_abc: [1, 2, 3],
  addled_bcd: [2], // error!
}
Run Code Online (Sandbox Code Playgroud)

在那之前,TypeScript 中没有特定类型可以代表您的需求。您可以在 TS4.1 到 TS4.3 中使用具有模板文字类型通用帮助函数,但此类函数更加复杂:

// TS 4.1-4.3
const asMyObject = <T extends { name: string } & { [K in keyof T]:
  K extends `added_${string}` | `removed_${string}` ? number[] :
  K extends "name" ? string :
  never }>(t: T) => t;

const myObject2 = asMyObject({
  name: "",
  added_abc: [1, 2, 3],
  added_bcd: [2],
  removed_abcd: [4, 5],
  removed_xyz: [],
}); // okay

const myBadObject2 = asMyObject({
  name: "",
  added_abc: [1, 2, 3],
  addled_bcd: [2], // error!  
});
Run Code Online (Sandbox Code Playgroud)

Playground 代码链接