Skip to content
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

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

Closed
karimbeyrouti opened this issue Oct 7, 2014 · 24 comments
Labels

Comments

@karimbeyrouti
Copy link

@karimbeyrouti karimbeyrouti commented Oct 7, 2014

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 ) .

@karimbeyrouti karimbeyrouti changed the title error TS2323: Type 'Timer' is not assignable to type 'number'. setTimeout - assigning timeout id to a variable throws an error TS2323: Type 'Timer' is not assignable to type 'number'. Oct 7, 2014
@RyanCavanaugh
Copy link
Member

@RyanCavanaugh RyanCavanaugh commented Oct 7, 2014

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.

@karimbeyrouti
Copy link
Author

@karimbeyrouti karimbeyrouti commented Oct 7, 2014

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 .

@NoelAbrahams
Copy link

@NoelAbrahams NoelAbrahams commented Oct 7, 2014

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

@karimbeyrouti
Copy link
Author

@karimbeyrouti karimbeyrouti commented Oct 7, 2014

Not sure what you mean by F12 ? .

@RyanCavanaugh
Copy link
Member

@RyanCavanaugh RyanCavanaugh commented Oct 7, 2014

"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.

@karimbeyrouti
Copy link
Author

@karimbeyrouti karimbeyrouti commented Oct 7, 2014

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...

@jdfreder
Copy link

@jdfreder jdfreder commented Apr 22, 2015

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).

@rixrix
Copy link

@rixrix rixrix commented Jan 7, 2016

@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.

@Penryn
Copy link

@Penryn Penryn commented Apr 21, 2016

@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!

@rixrix
Copy link

@rixrix rixrix commented Apr 21, 2016

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

@jeserkin
Copy link

@jeserkin jeserkin commented May 19, 2016

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

@kemsky
Copy link

@kemsky kemsky commented Oct 8, 2016

Just use window.setTimeout instead.

@cchamberlain
Copy link

@cchamberlain cchamberlain commented Jan 20, 2017

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

@Penryn
Copy link

@Penryn Penryn commented Jan 20, 2017

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

So not just a number in this case.

@cchamberlain
Copy link

@cchamberlain cchamberlain commented Jan 20, 2017

@Penryn - TIL 👍

@johnfn
Copy link

@johnfn johnfn commented Mar 22, 2017

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.

@cchamberlain
Copy link

@cchamberlain cchamberlain commented Mar 22, 2017

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

@AskYous
Copy link

@AskYous AskYous commented Apr 27, 2017

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).

@chunliu
Copy link

@chunliu chunliu commented May 13, 2017

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

@leocaseiro
Copy link

@leocaseiro leocaseiro commented Jun 28, 2017

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

mohsen1 pushed a commit to mohsen1/react-hot-ts that referenced this issue Jul 10, 2017
Mohsen Azimi
edgesite added a commit to edgesite/react-ts-webpack that referenced this issue Jul 17, 2017
Node.js' setTimeout returns entire Timer object and after upgrade
the TypeScript considered setTimeout returns NodeJS.Timer object
instead of a number. Changing to use window.setTimeout to distinguish
with Node.js.
See more details: microsoft/TypeScript#842
@Lavaei
Copy link

@Lavaei Lavaei commented Jul 23, 2017

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

@alexlee85
Copy link

@alexlee85 alexlee85 commented Oct 27, 2017

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

@nippur72
Copy link

@nippur72 nippur72 commented Jan 27, 2018

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

@riggs
Copy link

@riggs riggs commented Feb 23, 2018

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: DefinitelyTyped/DefinitelyTyped#21310 (comment)

@microsoft microsoft locked and limited conversation to collaborators Jun 25, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet