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

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

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

为什么类型允许第一个例子,但不允许第二种情况? 我在类型3.4.5

41329 次浏览

To get the type of a variable you need to use the typeof type operator:

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

Note:

Since there seems to be a lot of confusion when people use this. The const matters. If you use other types of declarations (let or var) the final type would be string. Only const preserves string literal types.

Note 2:

For this solution to work you must not specify any type annotation on the const, and let the compiler infer the type of the constants (ex this will not work :const MY_CONSTANT: string = 'MY_CONSTANT')

You can also use enum for this case. For example:

// 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

Enums cover the case quiet well:

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


export type IItemType = ITEM_TYPES.TYPE1 | ITEM_TYPES.TYPE2

And then in code ITEM_TYPES can be refered to for all kind of runtime comparisons:

if (type === ITEM_TYPES.TYPE1){
}

I made a post related to string literal union type. https://medium.com/@m.fatihalaziz/string-literal-union-type-with-typeguard-in-typescript-dff4c9741b4a

what it cover:

  • how to create a string literal union type
  • how to pass string as the string literal
  • how to use the type guard of typescript effectively

I hope it helps, Good Luck!