如何在 TypeScript 中迭代自定义文字类型?
Posted
技术标签:
【中文标题】如何在 TypeScript 中迭代自定义文字类型?【英文标题】:How can I iterate over a custom literal type in TypeScript? 【发布时间】:2017-04-13 07:23:17 【问题描述】:我在 TypeScript 中定义了一个自定义文字类型:
export type Market = 'au'|'br'|'de';
现在我想遍历每个可能的 Market
而不必首先创建一个 Market[]
数组,因为它感觉多余,我可能会忘记添加一个选项:
const markets: Market[] = ['au', 'br', 'de'];
markets.forEach((market: Market) =>
console.log(market);
);
有没有办法使用 TypeScript 来实现?
【问题讨论】:
这是不可能的,但我真的希望 TS 团队在类型中添加类似自省的东西,在运行时可用。 类型别名(和接口)的全部意义在于它们不会被编译成 javascript。如果你只想要编译的东西,那么你可以使用它,但如果你需要它用于运行时,那么你必须使用 js 中存在的东西。 【参考方案1】:对于那些使用 TypeScript >= 3.4 访问此问题的人,我相信现在最好的做法是创建一个字符串常量数组,然后使用运算符的类型。
例子:
export const markets = ['au', 'br', 'de'] as const;
export type Market = typeof markets[number];
markets.forEach((market: Market) =>
console.log(market);
);
【讨论】:
谢谢 :-)as const
是什么意思?
它告诉 Typescript 它是不可变的。 typescriptlang.org/docs/handbook/release-notes/…
在这种情况下,Market
类型等于string
(而不是'au'|'br'|'de'
)。这不是违背了目的吗?
@scale_tone - 不正确。市场类型不等于string
。 ` const 市场 = ['au', 'br', 'de'] 作为 const;市场类型=市场类型[数量];常量测试:市场='测试';类型 '"test"' 不能分配给类型 '"br" | “非” | “德”。 `
@keithhackbarth,确实如此。我一定是被 vscode 的提示给骗了。【参考方案2】:
我认为最容易理解的 TypeScript 3.9 的完整示例:
enum SupportedLangugesEnum
'au' = 'au',
'br' = 'br',
'de' = 'de',
for (let entry in SupportedLangugesEnum)
if (isNaN(Number(entry)))
console.log(entry);
for (let entry of Object.keys(SupportedLangugesEnum))
console.log(entry);
for (let entry of Object.values(SupportedLangugesEnum))
console.log(entry);
将打印:
来源:
https://***.com/a/39372911/3850405
【讨论】:
【参考方案3】:这是另一种方式:
enum Market
'eu' = 'eu',
'us' = 'us',
const all_possible_market_values = getStringValuesFromEnum(Market)
function getStringValuesFromEnum<T>(myEnum: T): (keyof T)[]
return Object.keys(myEnum) as any
基础表示不再是数字。这是字符串。
"use strict";
var Market;
(function (Market)
Market["eu"] = "eu";
Market["us"] = "us";
)(Market || (Market = ));
const all_possible_market_values = getStringValuesFromEnum(Market);
function getStringValuesFromEnum(myEnum)
return Object.keys(myEnum);
【讨论】:
【参考方案4】:以下是我要创建一个数组,该数组在运行时包含所有值并在编译时进行检查:
export type Market = 'eu' | 'us'
export const MARKET_TYPES: Market[] = (() =>
const markets: Market[] = ['eu', 'us']
return markets.map((x: Market) =>
if (x === 'eu')
return x
else if (x === 'us')
return x
else
const _exhaustive_check: never = x
return _exhaustive_check
)
)()
【讨论】:
你的地图不是总是返回x
吗?我看不出您的地图与此地图有何不同:.map((x: Market) => x)
。
我不会否决这个答案。我相信其目的是表明您可以创建一个类型,然后创建一个可用类型的数组以进行迭代。你用它做什么在 map 方法中是任意的。我真的很喜欢看到详尽的检查,更多的打字稿开发人员需要这样做。 +1【参考方案5】:
不,你不能这样做,因为像这样的纯类型信息在运行时不存在。
假设另一种方式是合理的(定义一个普通的字符串列表,然后从中派生 'au'|'br'|'de'
类型),但我认为 TypeScript 编译器(2.0 或 2.1)目前不会推断出对你来说——据我所知,市场类型通常总是string[]
。
对此的正确答案是使用枚举。他们为每个值定义了一个类型,并且可以获得所有字符串值的列表:How to programmatically enumerate an enum type in Typescript 0.9.5?。
枚举的一个缺点是它们的运行时表示不同(实际上它们是数字,而不是字符串)。您的代码仍然可以将它们视为很好的可读值,只是如果您在运行时需要它们作为字符串名称,则必须将它们转换为字符串。不过这很简单:给定枚举 MarketEnum
和值 myEnumValue
,MarketEnum[myEnumValue]
是值的名称作为字符串)。
【讨论】:
以上是关于如何在 TypeScript 中迭代自定义文字类型?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 TypeScript 中指定定义为对象文字的箭头函数的类型?
如何从 Typescript 中的常量定义字符串文字联合类型
TypeScript 如何知道自定义数组类型中长度字段的行为?