TypeScript中的类型化数组到文字类型
Posted
技术标签:
【中文标题】TypeScript中的类型化数组到文字类型【英文标题】:Typed Array to literal Type in TypeScript 【发布时间】:2021-12-18 11:36:56 【问题描述】:typed 字符串数组如何根据实际值用作 literal 类型的联合?在高层次上,我有一个像 ['hello', 'world']
这样的类型化数组,我想从中推断出一种新类型的 'hello' | 'world'
。
const someArray: Readonly<Array<string>> = ['hello', 'world'] as const;
type SomeType = typeof someArray[number]; // string
SomeType
现在将被推断为string
而不是联合。如何推断文字类型的联合?
这个问题与TypeScript array to string literal type 非常相似,不同之处在于数组是typed。我无法删除它。下面的代码可以工作,但someArray
实际上输入为Array<string>
。
const someArray = ['hello', 'world'] as const;
type SomeType = typeof someArray[number]; // 'hello' | 'world'
有没有办法相应地缩小推断类型?
edit:这个例子显然被简化了。我使用需要一组对象的第三方库。这些是由第三方键入的,如果不失去类型支持,我无法更改它。我意识到它可以在没有类型的情况下工作,但我无法真正删除它。
【问题讨论】:
这能回答你的问题吗? Typescript derive union type from tuple/array values 你已经找到了所有的答案——如果编译器必须继续运行的是string[]
,那么它显然没有创建联合的信息。
Readonly<Array<string>>
的优先级高于 as const
。
@HarunYilmaz 不,它没有。我知道它可以在没有类型的情况下工作,但我无法实际删除它(请参阅我的编辑)。我的问题是是否以及如何使用 类型来完成。
它不能,添加类型显式覆盖编译推断的任何内容。您必须显式键入元组(通过更改类型或显式转换为元组)或完全删除类型。
【参考方案1】:
您无法让 TypeScript 推断出与明确告知的内容直接矛盾的内容 (Readonly<Array<string>>
)。那种类型注解赢得了胜利。
正如您所指出的,修复方法是删除类型注释。但你说过你不能那样做。
由于您无法删除类型注释 - 例如,数组是由您无法控制的代码定义的 - 那么您别无选择,只能复制类型中的可能值列表,当原始更改并且您不更新副本时,这会使您面临维护问题。为了缓解这种情况,您可以添加运行时检查来处理原始更改导致它们不再匹配的情况:
const duplicatedArray = ['hello', 'world'] as const;
type SomeType = typeof duplicatedArray[number]; // 'hello' | 'world'
if ( someArray.length !== duplicatedArray.length ||
someArray.some((e, i) => e !== duplicatedArray[i]))
throw new Error(`'someArray' and 'duplicatedArray' no longer match`);
(其中的运行时部分可能在自动化测试中,而不是在主代码中。)
非常可以说是第二或第三的解决方案,但如果你别无选择,至少也可以。
【讨论】:
好的,感谢您的澄清。由于这(实际上)似乎不可能,我正在考虑手动创建联合类型并相应地缩小数据结构的类型定义。即使这使它稍微重复。 是的,这取决于原件的复杂程度。运行时检查在许多情况下都是现实的,但不是全部。在可能的情况下,它对于捕获错误很有用,但如果不是,则必须依靠手动流程...以上是关于TypeScript中的类型化数组到文字类型的主要内容,如果未能解决你的问题,请参考以下文章
TypeScript:来自字符串联合文字数组类型,不允许数组中存在任何冗余值
在 TypeScript 中使用类型变量访问对象文字不起作用
目前是不是有将两个或多个字符串文字类型连接到 TypeScript 中的单个字符串文字类型?