Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Narrowing string to string literal union

I want to narrow a string to a string literal union. In other words, I want to check if the string is one of the possible values of my literal union, so that this will work (if the operator couldbe existed).

type lit = "A" | "B" | "C";
let uni: lit;
let str = "B";
if(str couldbe lit){
    uni = str;
} else {
    doSomething(str);
}

How can I achieve this?

I tried using if (str instanceof lit), but that doesn't seem to work. Using keyof to iterate over the string union doesn't work either, because the allowed values aren't keys per se.

One way would be to use switch with one case for each possible value, but that could lead to subtle errors if lits allowed values change.

like image 664
iFreilicht Avatar asked May 16 '17 14:05

iFreilicht


People also ask

What is literal union?

A string literal union type is where we combine multiple string literal types together. Let's continue from the previous example and go through this. Let's enhance our Control type to be a union of string literals: type Control = "Textbox" | "DropDown"

What is string [] in TypeScript?

In TypeScript, the string is an object which represents the sequence of character values. It is a primitive data type which is used to store text data. The string values are surrounded by single quotation mark or double quotation mark. An array of characters works the same as a string.

What are examples of string literals?

A string literal is a sequence of zero or more characters enclosed within single quotation marks. The following are examples of string literals: 'Hello, world!' 'He said, "Take it or leave it."'


1 Answers

You can use User-Defined Type Guards.

type lit = "A" | "B" | "C";
let uni: lit;
let str = "B";

function isLit(str: string): str is lit {
    return str == "A" || str == "B" || str == "C";
}
function doSomething(str: string) {

}

if (isLit(str)) {
    uni = str;
}
else {
    doSomething(str);
}

ADD:

To avoid duplicated edit, class can be used both for compile-time and run-time. Now all you have to do is to edit just one place.

class Lit {
    constructor(public A = 0, public B = 0, public C = 0) {}
}
type lit = keyof Lit;
let uni: lit;

function isLit(str: string): str is lit {
    let lit = new Lit();
    return (str in lit) ? true : false;
}
like image 132
thatseeyou Avatar answered Nov 16 '22 03:11

thatseeyou