Typescript: setTimeout - assigning timeout id to a variable throws an error TS2323: Type 'Timer' is not assignable to type 'number'.

Created on 7 Oct 2014  ·  24Comments  ·  Source: microsoft/TypeScript

Using tsc v1.1.0-1 we get an error when compiling :
error TS2323: Type 'Timer' is not assignable to type 'number'.

the following code throws the compile error:

this.sTimeout = setTimeout( () => this.showDelay() , 250 );

sTimeout is defined as a number ( private var ) .

Question

Most helpful comment

Just use window.setTimeout instead.

All 24 comments

Please post a complete example. The information given so far is not enough to reproduce the issue:

class Foo {
    private sTimeout: number;
    showDelay() { }
    bar() {
        setTimeout(() => this.showDelay(), 250);
    }
}

There is no built-in type called Timer so it's likely that the setTimeout you're calling is not window.setTimeout.

Should have made an example - was a little rushed earlier. Here you go:

class Foo {
    private sTimeout: number; // Storing Timeout ID - to clear it - if needed
    private showDelay() { }
    constructor() {
        this.sTimeout = setTimeout(() => this.showDelay(), 250);
    }
}

Throws the following error:

Using tsc v1.1.0-1
/tests/Foo.ts(5,3): error TS2323: Type 'Timer' is not assignable to type 'number'.

For now I have fixed it using by typing sTimeout to any .

This does not repro for me. What happens when you F12 setTimeout?

Not sure what you mean by F12 ? .

"Go to definition"

Again, there is no built-in type called Timer, so your code must be referring to some other type. Please try out your example in a file by itself, or figure out where in your project this Timer is coming from. I'm guessing that setTimeout isn't referring to the built-in function, but rather some other user-defined function that has a different return value.

Tried the example by itself: looks like it is caused by a component in my toolchain or other code - sorry for taking your time. Thank you ... Closed...

For future readers, I came across this error because of the node.js definitely-typed definitions. The solution is to use the full name of the type, which is NodeJS.Timer not Timer (which sadly is what the Typescript transpiler suggests, and doesn't work).

@jdfreder time flies - the future is here

anyway I had the same issue: error TS2352: Neither type 'Timer' nor type 'number' is assignable to the other. even though I have the implicit reference defined at the top of the file /// <reference path="node_modules/typescript/lib/lib.d.ts" /> still doesn't work.

The main problem is that one of our 3rd party npm package (angular2) have TS + typings (node, and others) included in the package.

@rixrix (and for anyone else who finds this) I had a similar problem until I realized I wasn't passing in the correct parameters.

Compare this, which requires the second parameter ms and returns a NodeJS.Timer:

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

...and this, which does makes the second parameter timeout optional and returns a number:

function setTimeout(handler: any, timeout?: any, ...args: any[]): number;

Based on these two functions TS correctly selects an appropriate overload, so if you get error TS2352: Neither type 'Timer' nor type 'number' is assignable to the other make sure you specify a timeout!

Hi @Penryn thanks for the heads up!

I think my previous comment is a testament of not giving enough details as I can't remember anymore the exact details about the said error message. sorry.

On top of my head, the issue that we had before was when we do incremental upgrades of our spin off web app written in Angular2(alpha releases). Our main code base (ng1 and ng2) is written in TypeScript (with bower components, bunch of other typings, and few custom typings), and Angular2 at that time were shipping typings as well, node typings etc. With our node typings (outdated version) and ng2 node typings (and possibly other typings), effectively the TS compiler gets confused about dups typings. In our case, we could have manually modify the offending typings but it's just too much work knowing that some point we'll have to pull out the latest version(s)

I think this has been resolved in recent Angular2 releases as we'll have to manually install the required typings.

cheers

@RyanCavanaugh have same issue. I look, that I have two deffinitions for setTimeout. One returns number and the other returns NodeJS.Timer.

Just use window.setTimeout instead.

Why does the NodeJS.Timer require a special type? It's still just going to return a number right? Am I missing something?

@cchamberlain Node actually returns an entire Timer class: https://nodejs.org/api/timers.html

So not just a number in this case.

@Penryn - TIL 👍

For those curious, the reason this is happening is that setTimeout in node.js returns a different thing than setTimeout inside the browser. The browser's setTimeout just returns a number; in node.js setTimeout returns a big Timer object.

So the reason you're seeing this problem is almost certainly because you've intended to target the web, but you've pulled in node definitions.

@johnfn could also be isomorphic code intended to target browser and node.

For others coming in here using the setTimeout or setInterval, use window.setTimeout or interval so tsc knows you're using the web browser's function (which returns number) and not NodeJS's function (which returns something else).

To add on to @AskYous , if you have @types/node in the packages, use window.setInterval to avoid the type failure.

For who is using @angular with @angular-cli make sure you have the type node on your tsconfig.app.json as well.

Eq:

tsconfig.app.json

{
  "extends": "../tsconfig.json",
  "compilerOptions": {
    "outDir": "../out-tsc/app",
    "module": "es6",
    "baseUrl": "",
    "types": ["node"] --> ADD THIS
  },
  "exclude": [
    "test.ts",
    "**/*.spec.ts"
  ]
}

I found it here: https://stackoverflow.com/a/43952363/3415716

Maybe you have import a package that has a function with name setTimeout().
Just use window.setTimeout instead of setTimeout to solve the problem :)

in node environment type is NodeJS.Timer use global.setTimeout
and in browser environment type is number use window.setTimeout

today after installing npm i @types/react @types/react-dom --save-dev

the @types\node leaked into node_modules and thus it was causing the Timer error

Like @nippur72 , I ran into this today with react-dom. I think the simplest solution is to update the @types package to not depend on Node when a browser environment is expected, hence: https://github.com/DefinitelyTyped/DefinitelyTyped/issues/21310#issuecomment-367919251

Was this page helpful?
0 / 5 - 0 ratings