是否可以从数组创建打字稿类型?
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
,也可以在需要时遍历所有可用的东西。
这行得通,但感觉就像重复了两次信息。而且您必须小心,因为更新 Stuff
或 AVAILABLE_STUFF
也需要更新其对应项。
有没有更好的方法来定义数组的类型,或者甚至在某种程度上使用数组来输入一些数据?
【问题讨论】:
你想用类型填充数组还是这样使用数组的用例到底是什么? @MuratKaragöz 有点像。我希望只需一份声明就能从const x: Stuff
和AVAILABLE_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.4
和as 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 并将为我们提供元组中项目的类型。
(<T extends string[]>(...o: T)=> 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[]
【讨论】:
也是一个不错的解决方案以上是关于是否可以从数组创建打字稿类型?的主要内容,如果未能解决你的问题,请参考以下文章