Typescript: 从数组中的值创建类型

创建于 2018-10-22  ·  16评论  ·  资料来源: microsoft/TypeScript


TypeScript版本: 3.0.3


搜索字词:根据数组中的值进行输入

是否有当前或计划中的功能可以根据数组中的字符串创建类型?

const values = ['A', 'B']
type Foo = OneOf<values> // Is there a way of doing this?

const v1: Foo = 'A' // This should work
const v2: Foo = 'D' // This should give me an error since 'D' doesn't exist in values

类似于keyof工作方式:

const values = {
  A: 'A',
  B: 'B'
}
type Foo = keyof typeof values
const v1: Foo = 'A'
const v2: Foo = 'D' // Type '"D"' is not assignable to type '"A" | "B"'

相关问题:https://github.com/Microsoft/TypeScript/issues/20965

链接到游乐场http://www.typescriptlang.org/play/#src = let%20vals1%20%3D%20%5B'A'%2C%20'B'%5D%0D%0Atype%20Foo1%20% 3D%20OneOf%3Cvals1%3E%20%2F%2F%20Is%20there%20a%20way%20of%20doing%20this%3F%0D%0A%0D%0Alet%20v1%3A%20Foo1%20%3D%20' A'%20%2F%2F%20This%20should%20work%0D%0Alet%20v2%3A%20Foo1%20%3D%20'D'%20%2F%2F%20This%20should%20give%20me%20an% 20错误%20since%20'D'%20没有%20exist%20in%20values%0D%0A%0D%0Alet%20vals2%20%3D%20%7B%0D%0A%20%20A%3A%20'A '%2C%0D%0A%20%20B%3A%20'B'%0D%0A%7D%0D%0Atype%20Foo2%20%3D%20keyof%20typeof%20vals2%0D%0Alet%20v3%3A%20Foo2 %20%3D%20'A'%0D%0Alet%20v4%3A%20Foo2%20%3D%20'D'%20%2F%2F%20Type%20'%22D%22'%20is%20not%20assignedable %20to%20type%20'%22A%22%20%7C%20%22B%22'

Question

最有用的评论

[email protected]及更高版本中。 这样解决

export const type = <const>[
  'room',
  'room_with_gifter',
  'user_send'
];

export interface Activity {
  id?: string;
  type: typeof type[number];
}

所有16条评论

keyof只起作用,因为它使用在编译时静态已知的信息。 TS中的类型是完全可擦除的,并且在转码后的代码中不存在,因此,根本不可能基于数组的运行时内容创建类型。

这个有可能:

function stringLiterals<T extends string>(...args: T[]): T[] { return args; }
type ElementType<T extends ReadonlyArray<unknown>> = T extends ReadonlyArray<infer ElementType> ? ElementType : never;

const values = stringLiterals('A', 'B');
type Foo = ElementType<typeof values>;

const v1: Foo = 'A' // This should work
const v2: Foo = 'D' // This should give me an error since 'D' doesn't exist in values

绝对不知道如何执行此操作。 #27179是相关的。

但是,那仍然使用编译器静态已知的信息。 那时我不明白只说”A” | “B”的好处是什么。

@fatcerberus避免重复信息很有用-如果您只写const values = ["A", "B"]; type Foo = "A" | "B";则很容易有人更改其中一个而忘记更改另一个。 您可以编写const values: Foo[] =["A", "B"]; ,但是仍然很容易在Foo添加一个附加条目,而忘记将其放在values

现在我们在哪里?

就像@ andy-ms所说的那样,避免手动重复信息非常有用。
就像@fatcerberus所说,类型是完全可擦除的。 有时,我们有时需要运行时检查例如从应用程序的非纯粹部分(例如Web服务或用户)获得的数据。

以@ andy-ms的答案为基础,并使用打字稿3.4中引入的const断言,现在可以做这样的事情

const values = ['A', 'B'] as const
type ElementType < T extends ReadonlyArray < unknown > > = T extends ReadonlyArray<
  infer ElementType
>
  ? ElementType
  : never

type Foo = ElementType<typeof values> // this is correctly inferred as literal "A" | "B"

该问题被标记为“问题”,并且最近没有活动。 它已自动关闭以进行家政服务。 如果您仍在等待响应,那么问题通常更适合stackoverflow

[email protected]及更高版本中。 这样解决

export const type = <const>[
  'room',
  'room_with_gifter',
  'user_send'
];

export interface Activity {
  id?: string;
  type: typeof type[number];
}

代替这个:

export const items = <const>[
  'room',
  'room_with_gifter',
  'user_send'
];

export interface Activity {
  id?: string;
  type: typeof items[number];
}

你可以这样做:

export const items = [
  'room',
  'room_with_gifter',
  'user_send'
] as const;

export type Item = typeof items;

export interface Activity {
  id?: string;
  type: Item;
}

image

_真的不喜欢使用type作为变量名。_

@ 7公里

[email protected]及更高版本中。 这样解决

export const type = <const>[
  'room',
  'room_with_gifter',
  'user_send'
];

export interface Activity {
  id?: string;
  type: typeof type[number];
}

现在如果我在课堂上有这个怎么办?

class Class {
  const list = <const>[
   'room',
   'room_with_gifter',
   'user_send'
 ];

 const withType: typeof list[number];
}

不起作用。 我也不能做this.list[number] 。 另外,对于我来说
用例,我无法将list设置为static

@ 7公里

[email protected]及更高版本中。 这样解决

export const type = <const>[
  'room',
  'room_with_gifter',
  'user_send'
];

export interface Activity {
  id?: string;
  type: typeof type[number];
}

现在如果我在课堂上有这个怎么办?

class Class {
  const list = <const>[
   'room',
   'room_with_gifter',
   'user_send'
 ];

 const withType: typeof list[number];
}

不起作用。 我也不能做this.list[number] 。 另外,对于我来说
用例,我无法将list设置为static

@vegerot您不能在class的范围内直接使用const class ,因此语法不正确。

@ 7公里

[email protected]及更高版本中。 这样解决

export const type = <const>[
  'room',
  'room_with_gifter',
  'user_send'
];

export interface Activity {
  id?: string;
  type: typeof type[number];
}

现在如果我在课堂上有这个怎么办?

class Class {
  const list = <const>[
   'room',
   'room_with_gifter',
   'user_send'
 ];

 const withType: typeof list[number];
}

不起作用。 我也不能做this.list[number] 。 另外,对于我来说
用例,我无法将list设置为static

@vegerot您不能在class的范围内直接使用const class ,因此语法不正确。

@ 7kms,我不好。 我复制并粘贴过多。 我的意思是

class Class {
  private list = <const>[
   'room',
   'room_with_gifter',
   'user_send'
 ];

 private withType: typeof list[number];

// OR
  private withType2: typeof this.list[number];

}

等等都不起作用。
另外,对于我的特定用例,我无法将列表设置为静态

@ 7公里

[email protected]及更高版本中。 这样解决

export const type = <const>[
  'room',
  'room_with_gifter',
  'user_send'
];

export interface Activity {
  id?: string;
  type: typeof type[number];
}

现在如果我在课堂上有这个怎么办?

class Class {
  const list = <const>[
   'room',
   'room_with_gifter',
   'user_send'
 ];

 const withType: typeof list[number];
}

不起作用。 我也不能做this.list[number] 。 另外,对于我来说
用例,我无法将list设置为static

@vegerot您不能在class的范围内直接使用const class ,因此语法不正确。

@ 7kms,我不好。 我复制并粘贴过多。 我的意思是

class Class {
  private list = <const>[
   'room',
   'room_with_gifter',
   'user_send'
 ];

 private withType: typeof list[number];

// OR
  private withType2: typeof this.list[number];

}

等等都不起作用。
另外,对于我的特定用例,我无法将列表设置为静态

class Class {
  private list = [
    "room",
    "room_with_gifter",
    "user_send"
  ] as const

  private withType: Class["list"][number]
}

@vegerot这个怎么样?

@eyalch太棒了! 谢谢。 我认为解决方案将涉及typeof或其他东西。 您能快速解释一下它是如何工作的,或者将我链接到讨论它的手册上吗?

@eyalch太棒了! 谢谢。 我认为解决方案将涉及typeof或其他东西。 您能快速解释一下它是如何工作的,或者将我链接到讨论它的手册上吗?

@vegerot当然,我相信它是“索引类型”。 它在手册中: https: //www.typescriptlang.org/docs/handbook/advanced-types.html#index -types

很高兴我能帮助你!

嘿%username%,如果ElementType解决方案也不适合您,
注意array之后的as const 。 至关重要

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

blendsdk picture blendsdk  ·  3评论

Antony-Jones picture Antony-Jones  ·  3评论

CyrusNajmabadi picture CyrusNajmabadi  ·  3评论

weswigham picture weswigham  ·  3评论

seanzer picture seanzer  ·  3评论