TypeScript - используйте правильную версию setTimeout (node vs window)
Я работаю над обновлением старого кода TypeScript для использования последней версии компилятора, и у меня возникают проблемы с вызовом setTimeout
. Код ожидает вызова функции setTimeout
браузера, которая возвращает число:
setTimeout(handler: (...args: any[]) => void, timeout: number): number;
Однако компилятор вместо этого решает это для реализации узла, который возвращает NodeJS.Timer:
setTimeout(callback: (...args: any[]) => void, ms: number,...args: any[]): NodeJS.Timer;
Этот код не запускается в узле, но типизация узлов втягивается в зависимость от чего-то еще (не уверен, что).
Как я могу дать указание компилятору выбрать версию setTimeout
которую я хочу?
Вот код, о котором идет речь:
let n: number;
n = setTimeout(function () { /* snip */ }, 500);
Это приводит к ошибке компилятора:
TS2322: Тип "Таймер" не присваивается типу "номер".
Ответы
Ответ 1
Другое обходное решение, которое не влияет на объявление переменной:
let n: number;
n = <any>setTimeout(function () { /* snip */ }, 500);
Кроме того, должно быть возможно явно использовать объект window
без any
:
let n: number;
n = window.setTimeout(function () { /* snip */ }, 500);
Ответ 2
Я столкнулся с той же проблемой, и обходной путь, который наша команда решила использовать, заключалась только в том, чтобы использовать "any" для типа таймера. Например:
let n: any;
n = setTimeout(function () { /* snip */ }, 500);
Он будет работать с обеими реализациями методов setTimeout/setInterval/clearTimeout/clearInterval.
Ответ 3
Я бы предложил использовать x: ReturnType<typeof setTimeout>;
как это будет на самом деле работать независимо от используемой платформы.
Ответ 4
-
Если вы хотите найти реальное решение для машинописных писем о таймерах, мы пойдем:
Ошибка в обратном типе "номер" - это не таймер или что-то еще.
Это для версий типов скриптов ~> 2.7:
export type Tick = null | number | NodeJS.Timer;
Теперь мы зафиксировали все джуты, объявляющие вот так:
import { Tick } from "../../globals/types";
export enum TIMER {
INTERVAL = "INTERVAL",
TIMEOUT = "TIMEOUT",
};
interface TimerStateI {
timeInterval: number;
}
interface TimerI: TimerStateI {
type: string;
autoStart: boolean;
}
class myTimer extends React.Component<TimerI, TimerStateI > {
private myTimer: Tick = null;
private myType: string = TIMER.INTERVAL;
constructor(args){
super(args);
this.setState({timeInterval: args.timeInterval});
if (args.autoStart === true){
this.startTimer();
}
}
private myTick = () => {
console.log("Tick");
}
private startTimer = () => {
if (this.myType === TIMER.INTERVAL) {
this.myTimer = setInterval(this.myTick, this.timeInterval);
} else if (this.myType === TIMER.TIMEOUT) {
this.myTimer = setTimeout(this.myTick, this.timeInterval);
}
}
...
}
Ответ 5
По-видимому, вы можете импортировать функцию, если добавите пакет @types/core-js.
import { setTimeout } from 'core-js';
let n: number = setTimeout(function () { /* snip */ }, 500);
Ответ 6
Я думаю, это зависит от того, где вы будете запускать свой код.
Если ваша цель времени выполнения находится на стороне сервера Node JS, используйте:
let timeout: NodeJS.Timeout;
global.clearTimeout(timeout);
Если ваша цель времени выполнения - браузер, используйте:
let timeout: number;
window.clearTimeout(timeout);
Ответ 7
NodeJS.Timeout
кажется, работает для меня:
let timer: NodeJS.Timeout;
timer = setTimeout(console.log, 10);
Мой tsconfig
не имеет настроенных параметров compilerOptions
, это работает из коробки.