简体   繁体   English

Typescript 回调类型检查

[英]Typescript type check on callback

I have recently started learning Typescript and ran into this problem that I do not understand conceptually.最近开始学习Typescript,遇到了这个概念上看不懂的问题。 Is it wrong to define parameter type for this function?给这个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?我将如何 go 关于使 typescript 引发错误?

What are my solutions in general, when encountering something like this?遇到这样的事情时,我的一般解决方案是什么?

This is a known bug in TypeScript, see microsoft/TypeScript#32186 .这是 TypeScript 中的一个已知错误,请参阅microsoft/TypeScript#32186 The typings for setTimeout() look like setTimeout()的类型看起来像

setTimeout(handler: TimerHandler, timeout?: number, ...arguments: any[]): number;

which accepts any argument list whatsoever, without caring about the types.它接受任何参数列表,而不关心类型。 And TimerHandler is defined as justTimerHandler定义

type TimerHandler = string | Function

which uses the unsafe and untyped Function type .它使用不安全和无类型的Function类型 So setTimeout() is unfortunately very loosely typed in TypeScript.因此,不幸的是, setTimeout()在 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.这似乎只是 TS 中的一个限制。 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.您可以将 go 发送给 microsoft/TypeScript#32186 并给它一个并显示对它的修复的支持,但它不太可能发生太大变化。

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.可以决定使用您自己lib.dom.ts的本地副本,您可以在其中修改safeTimeout()的定义,但维护起来会非常烦人。

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:您可以使用的一种解决方法是将setTimeout包装在您自己的 function 中,它的类型更强,然后只使用它可能是这样的:

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.这使用generics来强类型化handler回调所期望的args与传递给setTimeout()本身的args相同。 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 .太好了,我们在5上得到了预期的编译器错误,说它应该是一个string而不是一个number That's about as good as it gets for now, unfortunately.不幸的是,这与现在一样好。

Playground link to code Playground 代码链接

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM