HiveBrain v1.2.0
Get Started
← Back to all entries
principletypescriptCritical

TypeScript - use correct version of setTimeout (node vs window)

Submitted by: @import:stackoverflow-api··
0
Viewed 0 times
typescriptusecorrectsettimeoutwindownodeversion

Problem

I am working on upgrading some old TypeScript code to use the latest compiler version, and I'm having trouble with a call to setTimeout. The code expects to call the browser's setTimeout function which returns a number:

setTimeout(handler: (...args: any[]) => void, timeout: number): number;

However, the compiler is resolving this to the node implementation instead, which returns a NodeJS.Timer:

setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]): NodeJS.Timer;

This code does not run in node, but the node typings are getting pulled in as a dependency to something else (not sure what).

How can I instruct the compiler to pick the version of setTimeout that I want?

Here is the code in question:

let n: number;
n = setTimeout(function () { /* snip */  }, 500);


This produces the compiler error: TS2322: Type 'Timer' is not assignable to type 'number'.

Solution

2021 update

Akxe's answer suggests ReturnType technique introduced in Typescript 2.3:

let n: ReturnType;
n = setTimeout(cb, 500);


It is nice and seems to be preferred over explicit casting. But the result type of "n" in this case is "NodeJS.Timeout", and it is possible to use it as follows:

let n: NodeJS.Timeout;
n = setTimeout(cb, 500);


The only problem with ReturnType/NodeJS.Timeout approach is that numeric operations in browser-specific environment still require casting:

if ((n as unknown as number) % 2 === 0) {
  clearTimeout(n);
}


Original answer

A workaround that does not affect variable declaration:
let n: number;
n = setTimeout(function () { / snip / }, 500) as unknown as number;


Also, in browser-specific environment it is possible to use window object with no casting:
let n: number;
n = window.setTimeout(function () { / snip / }, 500);

Code Snippets

let n: ReturnType<typeof setTimeout>;
n = setTimeout(cb, 500);
let n: NodeJS.Timeout;
n = setTimeout(cb, 500);
if ((n as unknown as number) % 2 === 0) {
  clearTimeout(n);
}

Context

Stack Overflow Q#45802988, score: 309

Revisions (0)

No revisions yet.