Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

type narrowing in typescript based on enum in type

say for example I have this type in typescript:

enum NumberOrStringType {
    NUMBER,
    STRING,
}

type NumberOrString = {
    dataType: NumberOrStringType,
    data: string | number;
};

and later in the code:

const numOrString: NumberOrString = { dataType: NumberOrStringType.NUMBER, data: 10 };

if (numOrString.dataType === NumberOrStringType.NUMBER) {
    const num: number = numOrString.data;
    ... 
} else {
    const str: string = numOrString.data;
    ...
}

Unfortunately, I get errors saying that type string | number is not assignable to type number and type string | number is not assignable to type string.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

I know I can just cast num and str by using as number and as string respectively, but is there a way to tell typescript to determine the type of data via the enum is has been assigned, or by narrowing the type by using an if statement?

>Solution :

You need to use a discriminated union: otherwise there is no way for Typescript to infer that when dataType is NumberOrStringType.NUMBER that data is always number, and vice versa for string.

type NumberOrString = {
    dataType: NumberOrStringType.NUMBER;
    data: number;
} | {
    dataType: NumberOrStringType.STRING;
    data: string;
}

Once you do that, you can use the satisfies operator to ensure TypeScript checks if your object satisfies the type, and your code should work:

const numOrString = { dataType: NumberOrStringType.NUMBER, data: 10 } satisfies NumberOrString;

if (numOrString.dataType === NumberOrStringType.NUMBER) {
    const num = numOrString.data; 
} else {
    const str = numOrString.data;

See playground example here.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading