具有已知前缀但完整键名未知的Typescript接口

4

有没有一种方法可以定义一个接口,使得键具有已知前缀(added_removed_),但完整键名未知?

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

{
   name: "",
   added_abc: [1,2,3],
   added_bcd: [2],
   removed_abcd: [4,5],
   removed_xyz: [],
}

我希望确保接口具备以下功能:

interface myobject {
   name: string;
   added_*?: number[];
   removed_*?: number[];
}
1个回答

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!
}

在那之前,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!  
});

代码操场链接


多么惊人的功能。谢谢分享。 - Marco

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接