生成联合字符串类型

时间:2019-07-09 07:42:28

标签: typescript

我正在验证字符串:

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提供带有数组的变量,那么Options类型将变为简单的stringany类型:

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

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

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

1 个答案:

答案 0 :(得分:0)

您的“双重赞美”想法可能是目前使此过程自动化的唯一方法。


在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];

再次,您可能要给问题加上?或描述您的用例(尽管我认为一般的字符串连接可能对此不适用)...再一次,我在这里不会期望太多时间很快。


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