Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does typeof typeguard not work when assigned to a variable?

I get a error when I use a typeof like below.

function func (variable: number | string) {
    const is_number = (typeof variable === 'number');
    let variable2: number,
        variable3: string;

    if (is_number)
        variable2 = variable;
        => Type 'string | number' is not assignable to type 'number'.
           Type 'string' is not assignable to type 'number'.
    else
        variable3 = variable;
        => Type 'string | number' is not assignable to type 'string'.
           Type 'number' is not assignable to type 'string'.
}

However, there is no error like below.

function func (variable: number | string) {
    let variable2: number,
        variable3: string;

    if (typeof variable === 'number')
        variable2 = variable;
    else
        variable3 = variable;
}

URL for test

Do I always have to use it like above? Or is there any part that I have used wrong?

Thanks for reading :)

like image 884
left click Avatar asked Jan 24 '26 12:01

left click


1 Answers

@Ry- already answered the actual question in the comments. Below is a workaround for the limitation.

It IS possible to do something similar to what you're trying to achieve with a helper function I'll call isNumber, that asserts whether a given argument extends a certain type in typescript. This provides a way to not inline a JS realm type assertion like typeof variable === "number" after all. Instead, the assertion is now contained in a function.

This is done using the x is y construct, which is called a Type predicate (You'll have to scroll down a bit). In the following snippet, the return type of isNumber is such a type predicate:

const isNumber = (subject: any): subject is number => {
    return typeof subject === 'number';
};

Here, typescript can infer the type number from the boolean returned from isNumber. Now, if you use this helper function in your own func, all should be good:

function func (variable: number | string) {
    let variable2: number;
    let variable3: string;

    if (isNumber(variable)) {
        variable2 = variable;
    } else {
        variable3 = variable;
    }
}

Since the if block will only ever be executed if isNumber(variable) returns true, Typescript will now assume that subject is number. The following pseudo code demonstrates how the above code should be interpreted by TS:

if (variable is number) {
    // ...
}

I also found this SO answer that further explains the type predicate construct.

like image 167
JJWesterkamp Avatar answered Jan 27 '26 02:01

JJWesterkamp