Home > Software engineering >  What is a good way to find which union the variable belongs to?
What is a good way to find which union the variable belongs to?

Time:08-25

I've been trying to create a function where the function's parameter is a union made from two other unions. I want it so that depending on the string passed into the parameter, a different function fires accordingly. Something like this:

type Type1 = "a" | "b" | "c";
type Type2 = "x" | "y" | "z";

function doSomething(param: Type1 | Type2) {
    // if param is a part of the "Type1" union
         functionForTypeOne();
}

doSomething("z");

I searched through the internet and the docs and I couldn't find a way to do this runtime type checking. I found some "solutions" for type checking, but they were all written for object types, not strings and unions.

In basic javascript, I could create a const array and check if the string is found inside the array, like so:

const type1 = ["a", "b", "c"];
const type2 = ["x", "y", "z"];

function doSomething(param) {
    if (type1.includes(param))
        functionForTypeOne();
}

Doing this in TypeScript is kind of a solution, but since I need to create unions from these consts, it feels very inefficient, and doesn't allow me to use the type checking features of the language. I was curious if anyone has a solution for this that I possibly overlooked, or if this is the only way for me to get around my problem.

CodePudding user response:

You can build the unions from your tuples almost automatically, and use a type guard predicate to recover type safety:

const type1 = ["a", "b", "c"] as const; // Assert as const to infer tuple instead of array string[]
const type2 = ["x", "y", "z"] as const;

// Automatically get union type from tuple values
type Type1 = typeof type1[number];
//   ^? "a" | "b" | "c"
type Type2 = typeof type2[number];
//   ^? "x" | "y" | "z"

// Type guard predicate
function isIn<T extends readonly string[]>(val: string, arr: T): val is T[number] {
    return arr.includes(val);
}

function doSomething(param: Type1 | Type2) {
    param
    //^? "a" | "b" | "c" | "x" | "y" | "z"
    if (isIn(param, type1)) {
        param
        //^? "a" | "b" | "c"
        //functionForTypeOne();
    }
}

Playground Link

CodePudding user response:

you may check this answer https://stackoverflow.com/a/54061487/2429434 There is no way to do what you want to do with your code.

  • Related