Skip to content

Type 'number' is not assignable to type 'Timeout' #30128

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
pronebird opened this issue Feb 27, 2019 · 8 comments
Closed

Type 'number' is not assignable to type 'Timeout' #30128

pronebird opened this issue Feb 27, 2019 · 8 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@pronebird
Copy link

pronebird commented Feb 27, 2019

TypeScript Version: 3.3.3

Search Terms:

Code

var timerId: NodeJS.Timeout = setTimeout(() => {}, 1000)

My config:

{
  "compilerOptions": {
    "alwaysStrict": true,
    "esModuleInterop": true,
    "jsx": "react",
    "module": "commonjs",
    "noImplicitReturns": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "outDir": "build",
    "resolveJsonModule": true,
    "rootDirs": [
      "src",
      "assets"
    ],
    "skipLibCheck": true,
    "strict": true,
    "target": "es2017",
    "lib": ["es2017", "dom"],
    "typeRoots": [
      "./types",
      "node_modules/@types"
    ]
  },
  "exclude": [
    "node_modules"
  ],
  "include": [
    "src/**/*.ts",
    "src/**/*.tsx"
  ]
}

Expected behavior:
No error. I have @types/node installed.

Actual behavior:
Error.

Playground Link:

Related Issues:
#842

@RyanCavanaugh RyanCavanaugh added the Working as Intended The behavior described is the intended behavior; this is not a bug label Feb 27, 2019
@RyanCavanaugh
Copy link
Member

You included the DOM typings in your lib, so TypeScript thinks you're calling the DOM version of setTimeout because it's basically ambiguous given two definitions of it. You can write global.setTimeout to disambiguiate.

@pronebird
Copy link
Author

Thanks @RyanCavanaugh. I guess I'll move on with global.. Thanks!

@yotam707
Copy link

For anyone else having this error what worked for me is adding in the tsconfig.js file:

"compilerOptions": {

   ...
   "types": [],
}

@SamHard
Copy link

SamHard commented Jun 30, 2020

The compiler is getting confused between global.setTimeout() and window.setTimeout(). In our application, we intended to use the browser's setTimeout method, so this resolved the mismatched types:
var timerId: number = window.setTimeout(() => {}, 1000)

@token-cjg
Copy link

NodeJS.Timeout is a more general type than number. To work around any type issues here when working purely in node and not in a browser, you can just prepend '+' to your global.setTimeout call, i.e. myTimeoutId: number = +global.setTimeout(() => {...}).

This is because NodeJS.Timeout uses Symbol.toPrimitive: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/121622b2e60d12c33f57683d931653c9e0a68680/types/node/globals.d.ts#L551 .

More docs on symbol.toPrimitive here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/toPrimitive .

bilalshaikh42 added a commit to biosimulations/biosimulations that referenced this issue Sep 8, 2021
Typescript compiler gets confused between which setTimeout is being used. See
microsoft/TypeScript#30128
bilalshaikh42 added a commit to biosimulations/biosimulations that referenced this issue Sep 8, 2021
Typescript compiler gets confused between which setTimeout is being used. See
microsoft/TypeScript#30128
@nicolasteofilo
Copy link

global.setTimeout

global.setTimeout worked in React: ^16.13.1.
thank man 😄

@twoco
Copy link

twoco commented Nov 19, 2022

I'm on Angular and declared timerId: number because in DOM context setInverval (and setTimeout) returns number. The tsconfig libs also includes dom. But I get the following error:

Type 'Timeout' is not assignable to type 'number'.ts(2322)

Because setInterval returns the NodeJS version (NodeJS.Timeout).

// Global scrope (lib.dom.d.ts)
function setInterval(callback: (...args: any[]) => void, ms: number, ...args: any[]): NodeJS.Timeout
// WindowOrWorkerGlobalScope (lib.dom.d.ts)
setInterval(handler: TimerHandler, timeout?: number, ...arguments: any[]): number;

In my opinion NodeJS should change that. But anyway, I wonder how can TypeScript provide the correct types in this context. A DOM context. How to tell TypeScript that I'm on browser and not on NodeJS.

As a workaround I could call window.setInterval. But this (window) should the global object for TypeScript in this context. I mean why can I call window if TypeScript thinks I'm in NodeJS and vice versa? I know ... But it would be great if we have a better solution.

Another use case: Have DOM (Browser) stuff on runtime but test in a NodeJS environment (Jest). Not sure if this really matter. But when working with type, this could be an issue. ...

@unoexperto
Copy link

unoexperto commented Aug 14, 2024

Could you folks please advice which types should I use in tsconfig.json to see .ts file where setInterval/setTimeout returns Timeout ? Currently IDEA opens node_modules/typescript/lib/lib.dom.d.ts for me which also has returning type as number.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

8 participants