如何将字符串文字类型定义为另一个字符串文字类型的子类型?

Posted

技术标签:

【中文标题】如何将字符串文字类型定义为另一个字符串文字类型的子类型?【英文标题】:How to define a string literal type as a subtype of another string literal type? 【发布时间】:2021-08-10 04:28:52 【问题描述】:

如何将字符串文字类型创建为另一个字符串文字类型的子类型?

或者换句话说,如何从字符串文字类型中选择值来创建新类型?

例子:

type Animal = 'goldfish' | 'tuna' | 'elephant'

// I would like to use Pick:
type Fish = Pick<Animal, 'goldfish', 'tuna'>

// So that the desired result is: 'goldfish | 'tuna'

但是,这不起作用,因为Pick 仅在选择(对象)属性键时起作用。

【问题讨论】:

你能澄清你的限制吗?你可以简单地把它作为一个单独的文字,比如type Fish = 'goldfish' | 'tuna';,或者作为一个交叉点,比如type Fish = Animal &amp; ('goldfish' | 'lion'); 我已将所需的结果添加到问题中,可能不清楚。你说得对,我希望 type Fish = 'goldfish' | 'tuna'; 作为最终结果,但我想从 Animal 中选择值来强制执行正确的值。 【参考方案1】:

您可以Extract,而不是Pick。不过,在这种使用字符串文字的情况下,它不会比&amp; 更进一步。

type Fish = Extract<Animal, 'goldfish' | 'lion'>   // 'goldfish'
type Fish2 = Animal & ('goldfish' | 'lion')        // 'goldfish'

在这两种情况下,请注意,如果您尝试选择不属于原始集合的条目,则不会出现编译时错误;它将被简单地省略。使用generic constraints (extends),您可以编写自己的Subset 类型来完成此操作。

type Subset<K, T extends K> = T;

type Fish3 = Subset<Animal, 'goldfish' | 'lion'>;  // compile error
type Fish4 = Subset<Animal, 'goldfish' | 'tuna'>;  // 'goldfish' | 'tuna'

Playground Link

【讨论】:

正是我需要的,谢谢杰夫。出于好奇,您知道为什么内置实用程序类型不支持此功能吗?字符串字面量类型很流行,并且直观地我希望它们也适用于这个...... @rei 很高兴为您提供帮助!对于为什么它不是内置的,我没有一个很好的答案,但幸运的是它很容易编写你自己的。获取两个通用参数并返回一个未修改的参数有点不寻常。如果我要猜测一个建议的替代方案,那就是在不检查的情况下定义字符串联合,将您的调用站点键入为 Animal,并让 TS 在调用站点而不是类型定义中强制执行。当然,这会将错误从问题/修复中传播出去,因此在这种情况下,Subset(或 AnimalSet,如果您制作了特定的)可能仍然更好,但代价是需要多行代码来定义 Subset。

以上是关于如何将字符串文字类型定义为另一个字符串文字类型的子类型?的主要内容,如果未能解决你的问题,请参考以下文章

如何定义具有重载的函数以恰好具有 1 或 2 个参数,这些参数的类型取决于使用的字符串文字

如何在打字稿中迭代字符串文字类型

打字模块 - 字符串文字类型

在接口中定义时,字符串文字类型的字段分配错误

目前是不是有将两个或多个字符串文字类型连接到 TypeScript 中的单个字符串文字类型?

为啥允许将字符串文字分配给 C++ 中 char * 类型的指针 [重复]