"TS2322: Type 'Timeout' is not assignable to type 'number'" when running unit tests

32,532

Solution 1

You could try with using window.setTimeout instead of just setTimeout, this way the typescript one will be explicitly used

Solution 2

You can use:

let timeoutId: null | ReturnType<typeof setTimeout> = null
...
timeoutId = setTimeout(...)

It'll pick correct declaration depending on your context.

I'm seeing this discrepency when using vscode/tsc (NodeJS.Timeout) and running ts-jest (number). This is the only way the whole thing typechecks on both sides.

Solution 3

By default, typescript includes all ./node_modules/@types/*. If you have ./node_modules/@types/node there, its timeout typings will override the web typing (that returns a number, and not a NodeJS.Timeout).

You can remedy to that by explicitly emptying your types in your tsconfig.json:

{
  "compilerOptions": {
    "types": []
  }
}

Realistically you're probably in a project where you need other types and libs so you might wanna bring back ES and DOM libs:

{
  "compilerOptions": {
    "types": [],
    "lib": ["ESNext", "DOM"]
  }
}
Share:
32,532
dawsonc623
Author by

dawsonc623

Updated on July 20, 2022

Comments

  • dawsonc623
    dawsonc623 almost 2 years

    I have two TypeScript packages, and one package (Package A) depends on the other (Package B). Each package has a unit test set up using Karma. When I run unit tests for each individually after installing all dependencies from NPM, the unit tests run fine. However, if I use npm link package-b in Package A and run Package A's unit tests then, I get the error stated in the title: "TS2322: Type 'Timeout' is not assignable to type 'number'."

    The line in question is a call to setTimeout. After digging, I found that while running the tests separately without npm link, TypeScript correctly identifies the setTimeout signature in typescript/lib/lib.dom as the desired type, but in the failing case after using npm link it is using using Node's setTimeout signature in @types/node/index. I confirmed this by changing the return type on setTimeout to string and observing the same error with string in the place of Timeout.

    What I am not certain of is why the TypeScript compiler has decided to use the alternative definition in this specific case, nor how I can convince it to use the desired definition. I am happy to post some code, but I am not sure what would be useful in this case given all that is on the failing line is the setTimeout call.