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, это работает из коробки.