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
Question An issue which isn't directly actionable in code

Comments

@karimbeyrouti
Copy link

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

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.

@RyanCavanaugh RyanCavanaugh added the Needs More Info The issue still hasn't been fully clarified label Oct 7, 2014
@karimbeyrouti
Copy link
Author

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

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

@karimbeyrouti
Copy link
Author

Not sure what you mean by F12 ? .

@RyanCavanaugh
Copy link
Member

"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

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

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

@joe-herman
Copy link

joe-herman 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 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

@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 commented Oct 8, 2016

Just use window.setTimeout instead.

@RyanCavanaugh RyanCavanaugh added Question An issue which isn't directly actionable in code and removed Needs More Info The issue still hasn't been fully clarified labels Oct 10, 2016
@cchamberlain
Copy link

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

@joe-herman
Copy link

@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

@Penryn - TIL 👍

@johnfn
Copy link

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

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

@AskYous
Copy link

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 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 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
edgesite pushed 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 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 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

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 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
Question An issue which isn't directly actionable in code
Projects
None yet
Development

No branches or pull requests