Я работаю над обновлением некоторого старого кода 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: Тип «Таймер» не может быть назначен типу «Число».
typescript
settimeout
Кевин Тай
источник
источник
types
не включает,node
но по-setTimeout
прежнему получает тип узла, а не тип браузера.types
по умолчанию для всех типов вnode_modules/@types
, как описано в typescriptlang.org/tsconfig#types , но даже если вы делаете указатьtypes
и не включают в себя"node"
, почему доsetTimeout
сих пор получить его тип узла , и как вы можете получить тип браузера? Решение @ Axke - это что-то вроде взлома, в основном говоря, что оно возвращает то, что возвращает. TypeScript может все еще находить неправильный тип, но, по крайней мере, он будет постоянно ошибаться.Ответы:
Другой обходной путь, не влияющий на объявление переменной:
let n: number; n = <any>setTimeout(function () { /* snip */ }, 500);
Кроме того, должно быть возможно использовать
window
объект явно безany
:let n: number; n = window.setTimeout(function () { /* snip */ }, 500);
источник
window.setTimeout
) должен быть правильным ответом на этот вопрос, поскольку это наиболее четкое решение.any
тип, вы на самом деле не даете ответа TypeScript.number
тип приведет к специфическим для TypeScript ошибкам lint, посколькуsetTimeout
функция требует большего.window.setTimeout
может вызвать проблемы с фреймворками модульного тестирования (node.js). Лучшее решение - использоватьlet n: NodeJS.Timeout
иn = setTimeout
.let timer: ReturnType<typeof setTimeout> = setTimeout(() => { ... }); clearTimeout(timer);
Используя,
ReturnType<fn>
вы получаете независимость от платформы. Вы не будете вынуждены использовать,any
иwindow.setTimeout
это не сломается, если вы запустите код без сервера nodeJS (например, страницу, отображаемую на стороне сервера).Хорошие новости, он также совместим с Deno!
источник
setTimeout
/clearTimeout
и не используемойany
.NodeJS.Timeout
приsetTimeout
прямом использовании иnumber
при использованииwindow.setTimeout
. Не нужно использоватьReturnType
.setTimeout
функцию и ожидаете, что ее результат будет сохранен в переменной. Попробуйте сами на игровой площадке TS.setTimeout
ошибается (по причинам, которые никто не может объяснить), но, по крайней мере, это решение должно маскировать это немного лучше, чем просто использованиеany
.Я думаю, это зависит от того, где вы будете запускать свой код.
Если вашей целевой средой выполнения является узел JS на стороне сервера, используйте:
let timeout: NodeJS.Timeout; global.clearTimeout(timeout);
Если вашей целевой средой выполнения является браузер, используйте:
let timeout: number; window.clearTimeout(timeout);
источник
Скорее всего, это будет работать со старыми версиями, но с версией TypeScript и версией
^3.5.3
Node.js^10.15.3
вы должны иметь возможность импортировать специфичные для Node функции из модуля Timers , то есть:import { setTimeout } from 'timers';
Это будет возвращать экземпляр таймаута типа ,
NodeJS.Timeout
который вы можете перейти кclearTimeout
:import { clearTimeout, setTimeout } from 'timers'; const timeout: NodeJS.Timeout = setTimeout(function () { /* snip */ }, 500); clearTimeout(timeout);
источник
setTimeout
, что-то вродеconst { setTimeout } = window
устранит эти ошибки.Я столкнулся с той же проблемой, и наша команда решила использовать обходной путь - просто использовать «любой» для типа таймера. Например:
let n: any; n = setTimeout(function () { /* snip */ }, 500);
Он будет работать с обеими реализациями методов setTimeout / setInterval / clearTimeout / clearInterval.
источник
window.setTimeout
может не работать с фреймворками модульного тестирования. Здесь есть тип, который можно использовать .. ЕгоNodeJS.Timeout
. Вы можете подумать, что находитесь не в среде узлов, но у меня для вас есть новости: Webpack / TypeScript и т. Д. Выполняют node.js.Если вы хотите реальное решение для машинописного текста о таймерах, мы идем:
Ошибка в возвращаемом типе «число», это не таймер или что-то еще.
Это решение для машинописных версий версии ~> 2.7:
Теперь мы все исправили, просто объявим вот так:
import { Tick } from "../../globals/types"; export enum TIMER { INTERVAL = "INTERVAL", TIMEOUT = "TIMEOUT", }; interface TimerStateI { timeInterval: number; } interface TimerI: TimerStateI { type: string; autoStart: boolean; isStarted () : bool; } class myTimer extends React.Component<TimerI, TimerStateI > { private myTimer: Tick = null; private myType: string = TIMER.INTERVAL; private started: boll = false; 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); this.started = true; } else if (this.myType === TIMER.TIMEOUT) { this.myTimer = setTimeout(this.myTick, this.timeInterval); this.started = true; } } private isStarted () : bool { return this.started; } ... }
источник
Если вы нацеливаетесь
setInterval
наwindow
. Тогда вы также можете написать это какlet timerId: number = setInterval((()=>{ this.populateGrid(true) }) as TimerHandler, 5*1000) }
источник