Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Turn a string literal type to a literal value

In TypeScript, we can have string literal types that allow us to do things like:

type HelloString = "Hello";

This lets me define something like a string enum as follows:

namespace Literals {
    export type One = "one";
    export type Two = "two";
}

And then I can define a union:

type Literal = Literals.One | Literals.Two;

Is there a way to extract the unique value of Literals.One as the type Literals.One?

The reason for this, is that when I define a function like this:

function doSomething(literal : Literal) {

}

I'd really love to do the following:

doSomething(Literals.One);

But I can't. I have to write:

doSomething("one");
like image 439
GregRos Avatar asked Nov 07 '16 10:11

GregRos


2 Answers

You can have types and values with the same name inside a namespace, so you can define constants for those values:

namespace Literals {
    export type One = "one";
    export type Two = "two";
    export const One: One = "one";
    export const Two: Two = "two";
}

const s: Literals.One = Literals.One;
console.log(s);

There is a probosal on github for string enums, they suggest the current best solution is the example above.

like image 188
Tamas Hegedus Avatar answered Oct 14 '22 20:10

Tamas Hegedus


Turning a string literal type to a literal value is possible with custom transformers (https://github.com/Microsoft/TypeScript/pull/13940), which is available in typescript@next.

Please look into my npm package, ts-transformer-enumerate.

Example usage:

// The signature of `enumerate` here is `function enumerate<T extends string>(): { [K in T]: K };`
import { enumerate } from 'ts-transformer-enumerate';

type Colors = 'green' | 'yellow' | 'red';
const Colors = enumerate<Colors>();

console.log(Colors.green); // 'green'
console.log(Colors.yellow); // 'yellow'
console.log(Colors.red); // 'red'
like image 21
kimamula Avatar answered Oct 14 '22 19:10

kimamula