是否可以从数组创建打字稿类型?

Posted

技术标签:

【中文标题】是否可以从数组创建打字稿类型?【英文标题】:Is it possible to create a typescript type from an array? 【发布时间】:2019-07-27 22:43:12 【问题描述】:

我经常使用诸如

之类的代码
export type Stuff = 'something' | 'else'
export const AVAILABLE_STUFF: Stuff[] = ['something', 'else']

这样我既可以使用类型Stuff,也可以在需要时遍历所有可用的东西。

这行得通,但感觉就像重复了两次信息。而且您必须小心,因为更新 StuffAVAILABLE_STUFF 也需要更新其对应项。

有没有更好的方法来定义数组的类型,或者甚至在某种程度上使用数组来输入一些数据?

【问题讨论】:

你想用类型填充数组还是这样使用数组的用例到底是什么? @MuratKaragöz 有点像。我希望只需一份声明就能从const x: StuffAVAILABLE_STUFF.forEach(stuff => ...) 的好处中获益。我不在乎我是否必须声明一个数组、一个类型或其他我还不知道的东西:) 你考虑过使用字符串enum吗?看起来它应该做你想做的事。它是一种类型,您可以迭代值。 与***.com/questions/51521808/…密切相关 【参考方案1】:

一个内置选项是使用枚举而不是类型和数组方法。

export enum Stuff 
    something = 'something',
    else = 'else',


export const AVAILABLE_STUFF: Stuff[] = Object.values(Stuff);

另一种选择是从AVAILABLE_STUFF 的类型中提取类型。为此,我们必须强制编译器推断AVAILABLE_STUFF 的字符串文字元组。这可以在3.4as const 中完成,或者在3.4 之前使用一个额外的函数来完成。在AVAILABLE_STUFF 是元组类型之后,我们可以使用类型查询来获取元素的类型:

export const AVAILABLE_STUFF = (<T extends string[]>(...o: T)=> o)('something', 'else'); // typed as ["something", "else"]
// export const AVAILABLE_STUFF = ['something', 'else'] as const; // typed as ["something", "else"]  in 3.4
export type Stuff = typeof AVAILABLE_STUFF[number] //"something" | "else"

上面代码的一些解释。 typeof AVAILABLE_STUFF 为我们提供了常量的类型 (["something", "else"]) 以获取 [number] 称为 type query 并将为我们提供元组中项目的类型。

(&lt;T extends string[]&gt;(...o: T)=&gt; o) 只是我们用来强制编译器推断字符串文字元组类型的 IIFE。它必须是通用的,因为编译器只会在某些情况下推断文字类型和元组(具有string 约束的类型参数就是其中之一)。 as const 版本是我建议在它可用时使用的版本,因为它更具可读性。

【讨论】:

在第二个解决方案中,我看到Stuff 类型被正确推断,但我不明白语法。 [number]typeof AVAILABLE_STUFF[number]中的作用是什么? @Paleo 添加了一些解释,让我知道现在是否更清楚了。 我明白了!谢谢。 @aherve 它不是一个完美的替代品。您需要在 TS 代码中使用 let a: Stuff = Stuff.something。在运行时a 的值将是something @MoshFeu 这应该可以:typescriptlang.org/play/…【参考方案2】:

Typescript v3.4 相当简单

你可以这样做-

export const AVAILABLE_STUFF = <const> ['something', 'else'];
export type Stuff = typeof AVAILABLE_STUFF[number];

更多信息 - https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-4.html#const-assertions

【讨论】:

为什么必须是AVAILABLE_STUFF[number] 而不仅仅是AVAILABLE_STUFF[] 因为数组中的“键”是数字。【参考方案3】:

另一种可能性是创建一个对象并使用keyof。仅当您有任何有用的值可存储为值时,我才建议使用这种方式(以替换下面代码中的 null)。

const stuffDict = 
  something: null,
  else: null,


type Stuff = keyof typeof stuffDict
const AVAILABLE_STUFF = Object.keys(stuffDict) as Stuff[]

【讨论】:

也是一个不错的解决方案

以上是关于是否可以从数组创建打字稿类型?的主要内容,如果未能解决你的问题,请参考以下文章

是否可以强制打字稿使用来自definitelyTyped 的类型而不是本机库类型?

如何从打字稿中的标记联合类型中提取类型?

打字稿用函数创建自己的类型

如何在打字稿中创建一个零数组?

打字稿:传播类型只能从对象类型创建

打字稿数组类型,其中输出是动态输入数量的所有可能组合