【问题标题】:Generating union string Type生成联合字符串类型
【发布时间】:2019-07-09 20:52:11
【问题描述】:

我正在验证一个字符串:

type Option = 'm' | 'm2' | 'm3' | 'ft' | 'ft2' | 'ft3'

const optionGood: Option = 'm'
const optionError: Option = 'other text' // Type '"other text"' is not assignable to type 'Option'.ts(2322)

这真的很麻烦,因为在真正的解决方案中,选项的数量是一个三位数。我很想创造这样的东西:

type Unit = 'm' | 'ft'
type Suffix = '' | '2' | '3'

// this line is fictional and doesn't work, but shows what I'm trying to accomplish
type Option = `${Unit}${Suffix}`

我尝试使用stringEnum 生成选项:

/** Utility function to create a K:V from a list of strings */
export function stringEnum<T extends string>(array: Array<T>): { [K in T]: K } {
  return array.reduce((res, key) => {
    res[key] = key
    return res
  }, Object.create(null))
}

const Options = stringEnum(['m', 'm2'])
// 'm' | 'm2'
type Options = keyof typeof Options

这仅适用于静态数组。如果您尝试将带有数组的变量提供给stringEnum,选项类型将变得简单stringany 类型:

const options = ['m', 'm2']
const Options = stringEnum(options)
// string
type Options = keyof typeof Options

我有一组要包含在Options 类型中的所有选项,但我不确定如何处理。所以我的问题是,如何从数组中生成联合字符串类型?

我什至开始考虑生成Options.ts 文件的Node 任务(双重编译?)。

【问题讨论】:

  • 类型系统不支持进行字符串操作。如果你真的想编译时验证这样的类型,那么生成一个 ts 文件是要走的路。

标签: typescript


【解决方案1】:

您的“双重编译”想法可能是目前实现自动化的唯一方法。


GitHub 中有一个支持regular-expression-validated string types 的建议,但这并没有成为 TS3.5 的语言,而且似乎也没有出现在近期的路线图上。如果是这样,您也许可以做类似的事情

// ⚠ the next line is just proposed syntax and does not currently work in TS ⚠
type Option = /^(m|ft)[23]?$/

如果您认为它比现有的内容更引人注目,您可能想继续讨论该问题并给它一个 ? 或描述您的用例......但我不会屏住呼吸等待这个。


GitHub 中的另一个相关问题是支持augmenting keys in mapped types 的建议。从 TS3.5 开始,此功能也不是该语言的一部分,并且看起来并未在积极开发中。如果它存在,您也许可以执行类似的操作

type Unit = 'm' | 'ft'
type Suffix = '' | '2' | '3'
// ⚠ the next line is just proposed syntax and does not currently work in TS ⚠  
type Option = { [S in Suffix]: keyof { [U in Unit] + S: any } }[Suffix];

再一次,你可能想给这个问题一个 ? 或描述你的用例(尽管我认为一般的字符串连接可能不适合这个)......再说一次,我不会期望太多很快。


哦,好吧。希望能有所帮助。祝你好运!

【讨论】:

    猜你喜欢
    • 2017-07-05
    • 1970-01-01
    • 2021-10-27
    • 2021-04-06
    • 2018-04-28
    • 1970-01-01
    • 2020-12-10
    • 2020-06-07
    相关资源
    最近更新 更多