从数组类型生成Typescript接口

7

我需要强制一个数组具有一组特定的值,这些值应该成为我的接口中的键。 我可以使用以下方法强制数组:

type SomeProperties = ['prop1', 'prop2', 'prop3'];

但我不知道如何强制接口具有这些属性。我尝试了类似于以下内容的东西:

type MyInterface = {
  [key in keyof SomeProperties]: string;
}

但是显然,数组的键只是数字,所以我的接口变成了

interface MyInterface {
  0: string;
  1: string;
  2: string;
}

替代所需要的接口

interface MyInterface {
  prop1: string;
  prop2: string;
  prop3: string;
}

您知道在TypeScript中是否有实现这个功能的方法吗?

这将非常有用,因为我需要迭代一些属性来“克隆”一个对象,并且我还需要轻松地访问这些属性。对于我来说,在类型和接口中重复这些属性有点脆弱。


尝试将 keyof SomeProperties 更改为 SomeProperties[number] - jcalz
@jcalz 这是一个好主意,但不幸的是它不起作用,IDE 给我提示的属性像 lengthatcharAt 等等,但没有 prop1prop2prop3 :( - Julo
不是 keyof SomeProperties[number];只是 SomeProperties[number] - jcalz
@jcalz 那个方法可行,谢谢!如果你创建答案,我可以接受它作为最佳答案。 - Julo
3个回答

7
正如您所指出的,您尝试访问的字符串并不是SomeProperties,而是SomeProperties元素
在这里,您可以使用索引访问运算符:如果KT的一个键(或键的联合),那么T[K]就是对应于访问TK键(们)的属性类型(或属性类型的联合)。
元组和数组接受number作为键类型,因此您可以使用SomeProperties[number]来获得联合类型"prop1"|"prop2"|"prop3"
type SomeProperties = ['prop1', 'prop2', 'prop3'];

type MyInterface = {
  [K in SomeProperties[number]]: string;
}

const myInterface: MyInterface = {
  prop1: 'this',
  prop2: 'works',
  prop3: 'now'
}

Playground link to code


6
值得注意的是:在 TypeScript 中,你不能迭代元组类型。
实际上,自从 TypeScript 3.1 版本以来,你可以安全地在对象映射类型中使用元组类型。详情请参见:可映射的元组和数组类型
这些操作只能应用于类型(type),而不是接口(interface)。
type SomeProperties = 'prop1' | 'prop2' | 'prop3';

type MyType = Record<SomeProperties, string>;

// equivalent to
// type MyType = {
//   [key in SomeProperties]: string
// }

从消费者的角度来看,类型和接口是相同的(当您请求一个MyType时,您并不在意它是一个接口还是一个类型,在这一点上它们是相同的)


我会使用类型来修改我的问题,抱歉。 那么你认为实现我所要求的是不可能的吗? - Julo
我认为这是一个更好的选择,除非你正在处理数组,例如对于通用:const ATTACK = "attack"; const CARRY = "carry"; const CLAIM = "claim"; const WORK = "work";type EnumDictionary<Enum extends string, TValue> = { [K in Enum]: TValue };const CREEP_BODY_PART_COST: EnumDictionary< ATTACK | CARRY | CLAIM, number
= { attack: 80, // OK carry: 50, // OK claim: 600, // OK work: 100 // FAIL };
- dropbeardan
1
@DropBearDan Screeps 万岁! - Madara's Ghost

0

针对未来读者,更新Madara的答案。

这些操作只能应用于类型,而不是接口。

我不知道从什么时候开始,但现在你也可以在接口中做到这一点。

type SomeProperties = 'prop1' | 'prop2' | 'prop3';

interface MyType extends Record<SomeProperties, string> {
   // other properties
}

这相当于以下内容:

type SomeProperties = 'prop1' | 'prop2' | 'prop3';

type MyType = Record<SomeProperties, string>;

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