如何从 Typescript 中的常量定义字符串文字联合类型

Posted

技术标签:

【中文标题】如何从 Typescript 中的常量定义字符串文字联合类型【英文标题】:How to define string literal union type from constants in Typescript 【发布时间】:2019-10-09 07:38:48 【问题描述】:

我知道我可以定义字符串联合类型以将变量限制为可能的字符串值之一:

type MyType = 'first' | 'second'
let myVar:MyType = 'first'

我需要从常量字符串构造一个类似的类型,例如:

const MY_CONSTANT = 'MY_CONSTANT'
const SOMETHING_ELSE = 'SOMETHING_ELSE'
type MyType = MY_CONSTANT | SOMETHING_ELSE

但由于某种原因它不起作用;上面写着MY_CONSTANT refers to a value, but it being used as a type here

为什么 Typescript 允许第一个例子,而不允许第二个例子?我在 Typescript 3.4.5

【问题讨论】:

听起来你真正想要的是enum...? 你想要type MyType = typeof MY_CONSTANT | typeof SOMETHING_ELSE。类型(仅在设计时存在)和值(在运行时存在)之间存在很大差异 当我感觉到类型和值之间存在混淆时,我经常向人们抛出this answer。 @T.J.Crowder 考虑到了这一点,但我有在其他地方定义的常量字符串,我想使用 @CanPoyrazoğlu - 很公平,那么提香的答案就是你想要的。 【参考方案1】:

要获取变量的类型,您需要使用typeof 类型运算符:

const MY_CONSTANT = 'MY_CONSTANT' // must be const, no annotation. let or var will not work
const SOMETHING_ELSE = 'SOMETHING_ELSE' // must be const, no annotation. let or var will not work
type MyType = typeof MY_CONSTANT | typeof SOMETHING_ELSE

Playground

注意:

因为人们使用它时似乎有很多困惑。 const 很重要。如果您使用其他类型的声明(letvar),最终类型将是字符串。只有 const 保留字符串文字类型。

注2:

要使此解决方案起作用,您必须const 上指定任何类型注释,并让编译器推断常量的类型(例如,这将不起作用 :const MY_CONSTANT: string = 'MY_CONSTANT')

【讨论】:

@CanPoyrazoğlu 'test' 根据定义既是值又是类型(字符串字面量类型)(就像类是值、构造函数和类型、实例类型一样) typeof MY_CONSTANT 将检查它是否是string,而不是MY_CONSTANT 如果有人能解释对此答案的反对票,我将不胜感激。我坚持这个答案,它仍然做了它应该做的事情,并且是对原始问题的回答。如果有人对此有任何问题,请告诉我 @JonasRosenqvist 请阅读 cmets 和注释。请检查相关的游乐场链接。如果您使用 const 则文字类型将被保留,并且类型检查会按您的预期工作,并且并非所有字符串都兼容。如果您有一个不正确的示例,我希望看到它。抱歉,如果我听起来有点生气,但是这个答案一直无缘无故地被否决,而且变得非常烦人。不知道我能做些什么来使它更清楚 const 是必需的 @TitianCernicova-Dragomir - 你是对的,我错误地将常量声明为:const MY_CONSTANT:string = 'MY_CONSTANT' 指定常量的类型使其接受任何字符串。对不起,你会得到我的支持!【参考方案2】:

您也可以在这种情况下使用枚举。例如:

// Define enum.
enum myConstants 
  MY_CONSTANT = 'my_constant',
  SMTH_ELSE = 'smth_else'


// Use it in an interface for typechecking.
interface MyInterface 
  myProp: myConstants


// Example of correct object - no errors.
let a: MyInterface = 
  myProp: myConstants.MY_CONSTANT


// Incorrect value - TS reports an error.
let b: MyInterface = 
  myProp: 'John Doe'

More about enums

【讨论】:

这正是我想要的。【参考方案3】:

枚举很好地涵盖了这个案例:

export enum ITEM_TYPES 
    TYPE1 = 'text',
    TYPE2 = 'image'


export type IItemType = ITEM_TYPES.TYPE1 | ITEM_TYPES.TYPE2

然后在代码中可以引用 ITEM_TYPES 进行各种运行时比较:

if (type === ITEM_TYPES.TYPE1)

【讨论】:

以上是关于如何从 Typescript 中的常量定义字符串文字联合类型的主要内容,如果未能解决你的问题,请参考以下文章

在 Visual Studio 代码中,如何跳转到 typescript 类型定义 index.d.ts 中的实际代码?

LayaBox---TypeScript---枚举

TypeScript入门七:TypeScript的枚举

定义全局常量

如何测试使用 jasmine + TypeScript 使用常量调用的函数

如何在打字稿中定义一个常量数组