【问题标题】: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 中选择值来强制执行正确的值。

标签: typescript


【解决方案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。
猜你喜欢
  • 1970-01-01
  • 2020-02-23
  • 2020-09-17
  • 2011-04-14
  • 2013-08-27
  • 2022-08-09
  • 2020-08-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多