Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to define string literal union type from constants in Typescript

I know I can define string union types to restrict variables to one of the possible string values:

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

I need to construct a type like that from constant strings, e.g:

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

But for some reason it doesn't work; it says MY_CONSTANT refers to a value, but it being used as a type here.

Why does Typescript allow the first example, but doesn't allow the second case? I'm on Typescript 3.4.5

like image 546
Can Poyrazoğlu Avatar asked May 22 '19 18:05

Can Poyrazoğlu


People also ask

How do you define string literal TypeScript?

A string literal type is a type whose expected value is a string with textual contents equal to that of the string literal type. In other words: A variable of a string literal type can only be assigned the exact string value specified in the string literal type.

How do you declare a union type variable in TypeScript?

TypeScript 1.4 gives programs the ability to combine one or two types. Union types are a powerful way to express a value that can be one of the several types. Two or more data types are combined using the pipe symbol (|) to denote a Union Type.

What are literal types in TypeScript?

There are three sets of literal types available in TypeScript today: strings, numbers, and booleans; by using literal types you can allow an exact value which a string, number, or boolean must have.

Is string literal const?

String constants, also known as string literals, are a special type of constants which store fixed sequences of characters. A string literal is a sequence of any number of characters surrounded by double quotes: "This is a string."


2 Answers

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')

like image 111
Titian Cernicova-Dragomir Avatar answered Sep 29 '22 06:09

Titian Cernicova-Dragomir


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

like image 39
Eugene Avatar answered Sep 29 '22 07:09

Eugene