Space Cat, Prince Among Thieves

The Trouble with TypeScript Timeouts

I've run into this problem a number of times where I'm developing frontend TypeScript and after I import a package, I suddenly find throughout my project I'm receiving:

error TS2322: Type 'Timeout' is not assignable to type 'number'.

If you are working on a node project rather than a front end project this can also manifest itself as the opposite Type 'number' is not assignable to type 'Timeout'

Usually this happens because a dependency you've included has included @types/node under dependencies when it should have included it under devDependencies. Usually, unless you are actually developing a type package, @types packages should be a dev dependency.

The ideal solution would be for the package to fix the problem and you to pull the corrected version of the package. This however might not be possible, with the issue going ignored for months if not years - as on Facebook's Jest package [1] [2].

So let us take the following example line

let x : number = setTimeout(() => console.log("foo"), 1000);

Your immediate reaction might be to either change the definition to let x : Timeout or eliminate the explicit type definition all together ala

let x = setTimeout(() => console.log("foo"), 1000);

Both of these options work.

The first option of setting it to Timeout suffers from two issues though. Firstly it's fragile - presumably you're not explicitly including @types/node so the change to the environment here is a side effect you're coding around. Should the specific packages you include change, or said package correct this it will break.

The second option of implicit typing will work in a lot of cases just fine. There are many cases where you'd want for instance to define the variable in a higher scope than you are setting it's value - as a trivial example

class Foo {
    private x? : number;

    start() {
        this.x = setTimeout(() => console.log("foo"), 1000);
    }

    stop() {
        clearTimeout(this.x);
    }
}

The answer is frustratingly simple. We can just use the ReturnType utility type to set our type to the return type of setTimeout. We can do this using ReturnType<typeof setTimeout>.

Our examples from above become

let x : ReturnType<typeof setTimeout> = setTimeout(() => console.log("foo"), 1000);

and

class Foo {
    private x?: ReturnType<typeof setTimeout>;

    start() {
        this.x = setTimeout(() => console.log("foo"), 1000);
    }

    stop() {
        clearTimeout(this.x);
    }
}

Read More / Comment »

Recent Comments

While this tool is useful, I wish it had a thickness feature too. I use it to plan circles in Dwarf Fortress, but that includes moats which need to be several t…
Link

Thx a lot I want to build a megabase in survival and this helps me a lot ????
Link

im very happy this app was realy help me to build circle
Link

if i ever become a big minecraft youtuber, i will recommend this, thanks
Link

I wish that there where line down each middle
Link