TypeScript:在对象上强制执行单个动态键

jam*_*ase 3 typescript typescript-typings

有没有办法为具有单个动态命名键的对象编写接口?

我可以编写一个接口来接受任意数量的动态命名的键,但我想将其限制为一个。

让我们从一些基础知识开始,然后逐步解决我的问题。在下面的界面中,对象只能有一个键,命名为“id”:

interface Test {
  id: string
}
Run Code Online (Sandbox Code Playgroud)

这很好,因为具有此接口的对象只能具有一个属性id. 但我需要消费者能够指定这个键的名称。

如果我将该接口更改为以下内容,则它允许消费者指定自定义键:

type Test<K extends string> = {
  [P in K]: string
}
Run Code Online (Sandbox Code Playgroud)

这让我更接近我正在寻找的东西,正如我们在这个例子中看到的:

type SpecificTest = Test<"customId">;

const test:SpecificTest = {
  customId: 'pls',
}
Run Code Online (Sandbox Code Playgroud)

然而,用户可以传递一个联合类型来定义多个 ID 字段,这就是问题所在。

// I don't want a user to be able to pass multiple strings here
type SpecificTest = Test<"customId"|"anotherId">;

const test:SpecificTest = {
  customId: 'pls',

  // :(
  anotherId: 'blah'
}
Run Code Online (Sandbox Code Playgroud)

我在想这些方面的事情可能会奏效(在伪代码中):

type Test<K extends string> = {
  [K]: string
}
Run Code Online (Sandbox Code Playgroud)

但该特定语法不起作用。

有什么办法来定义的界面,用户可以只定义一个单一的动态名为key?

Nur*_*yev 5

您可以通过IsUnion辅助类型检测传递的类型是否为联合

type Test<K extends string> = IsUnion<K> extends true ? Error<'Please don\'t pass a union'>  : {
  [P in K]: string
}

interface Error<M> {msg: M}
Run Code Online (Sandbox Code Playgroud)