在运行单元测试时,“ TS2322: 类型‘ Timeout’不可分配给类型‘ number’”

我有两个 TypeScript 包,其中一个包(包 A)依赖于另一个包(包 B)。每个软件包都使用 Karma 设置了一个单元测试。在安装了来自 NPM 的所有依赖项之后,对每个测试单独运行单元测试时,单元测试运行良好。但是,如果我在包 A 中使用 npm link package-b并运行包 A 的单元测试,那么我会得到标题中提到的错误: “ TS2322: 键入‘ Timeout’不能分配给键入‘ number’。”

有问题的电话是打给 setTimeout的。深入研究之后,我发现 TypeScript 在不使用 npm link单独运行测试时,正确地将 typescript/lib/lib.dom中的 setTimeout签名识别为所需类型,但在使用 npm link失败的情况下,它在 @types/node/index中使用的是 Node 的 setTimeout签名。我通过将 setTimeout上的返回类型更改为 string并在 npm link0的位置观察到与 string相同的错误来确认这一点。

我不确定的是 为什么 TypeScript 编译器已经决定在这个特定的情况下使用替代定义,也不知道我如何说服它使用所需的定义。我很乐意发布一些代码,但是我不确定在这种情况下什么是有用的,因为所有的故障行是 setTimeout调用。

52856 次浏览

You could try with using window.setTimeout instead of just setTimeout, this way the typescript one will be explicitly used

You can use:

let timeoutId: null | ReturnType<typeof setTimeout> = null
...
timeoutId = setTimeout(...)

It'll pick correct declaration depending on your context.

I'm seeing this discrepency when using vscode/tsc (NodeJS.Timeout) and running ts-jest (number). This is the only way the whole thing typechecks on both sides.

You can use something like:

let myTimeOut: NodeJS.Timeout | null = null;


myTimeOut = setTimeout(...);

Then when you reset your variable to initial status, you can simply:

myTimeOut = null;

By default, typescript includes all ./node_modules/@types/*. If you have ./node_modules/@types/node there, its timeout typings will override the web typing (that returns a number, and not a NodeJS.Timeout).

You can remedy to that by explicitly emptying your types in your tsconfig.json:

{
"compilerOptions": {
"types": []
}
}

Realistically you're probably in a project where you need other types and libs so you might wanna bring back ES and DOM libs:

{
"compilerOptions": {
"types": [],
"lib": ["ESNext", "DOM"]
}
}

For me helped "strict": false in tsconfig.json