Issue
I have recently started learning Typescript and ran into this problem that I do not understand conceptually. Is it wrong to define parameter type for this function?
setTimeout((a: string) => {
console.log(a); // ==> Prints 5 as a number
}, 1, 5);
Why isn't there type checking performed when calling callback?
How would I go about making typescript throw an error?
What are my solutions in general, when encountering something like this?
Solution
This is a known bug in TypeScript, see microsoft/TypeScript#32186. The typings for setTimeout() look like
setTimeout(handler: TimerHandler, timeout?: number, ...arguments: any[]): number;
which accepts any argument list whatsoever, without caring about the types. And TimerHandler is defined as just
type TimerHandler = string | Function
which uses the unsafe and untyped Function type. So setTimeout() is unfortunately very loosely typed in TypeScript. Often in situations like this you could use declaration merging to add better call signatures, but in this case nothing will stop the compiler from falling back to the unsafe call signature.
This is just a limitation in TS, it seems. The issue is listed as being in the "Backlog", so it's not slated to be addressed anytime soon. You could go to microsoft/TypeScript#32186 and give it a 👍 and show support for it being fixed, but it's not likely to change much.
For now there are only workarounds.
You could decide to use your own local copy of the lib.dom.ts library, where you modify the definition of safeTimeout(), but that would be very annoying to maintain.
A workaround you could use is to wrap setTimeout in your own function that is more strongly typed, and then use only that Perhaps something like this:
const safeSetTimeout: <A extends any[]>(
handler: (...args: A) => void, timeout?: number, ...args: A
) => number = setTimeout;
That uses generics to strongly type the args expected by the handler callback to be same as that passed as the args passed to setTimeout() itself. Let's see it work:
safeSetTimeout((a: string) => {
console.log(a);
}, 1, 5); // <-- error! number is not assignable to string
// ~
Great, we get the expected compiler error on 5, saying that it should be a string and not a number. That's about as good as it gets for now, unfortunately.
Answered By - jcalz
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.