Saya sedang mengupgrade beberapa kode TypeScript lama untuk menggunakan versi kompiler terbaru, dan saya mengalami masalah dengan panggilan ke setTimeout
. Kode mengharapkan untuk memanggil fungsi browser setTimeout
yang mengembalikan angka:
setTimeout(handler: (...args: any[]) => void, timeout: number): number;
Namun, kompilator menyelesaikan ini ke implementasi node, yang mengembalikan NodeJS.Timer:
setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]): NodeJS.Timer;
Kode ini tidak berjalan dalam node, tetapi pengetikan node ditarik sebagai ketergantungan pada sesuatu yang lain (tidak yakin apa).
Bagaimana saya dapat menginstruksikan kompilator untuk memilih versi setTimeout
yang saya inginkan?
Berikut kode yang dimaksud:
let n: number;
n = setTimeout(function () { /* snip */ }, 500);
Ini menghasilkan kesalahan kompiler:
TS2322: Ketik 'Timer' tidak dapat digunakan untuk mengetik 'nomor'.
sumber
types
tidak menyertakannode
tetapisetTimeout
masih mendapatkan tipe Node daripada tipe browsernya.types
default untuk semua jenis dinode_modules/@types
, seperti yang dijelaskan dalam typescriptlang.org/tsconfig#types , tetapi bahkan jika Anda lakukan menentukantypes
dan tidak termasuk"node"
, mengapasetTimeout
masih mendapatkan jenis Node dan bagaimana Anda bisa mendapatkan jenis browser? Solusi @ Axke adalah sedikit hack, pada dasarnya mengatakan itu mengembalikan apa yang dikembalikannya. TypeScript mungkin masih menemukan jenis yang salah, tetapi setidaknya itu akan selalu salah.Jawaban:
Solusi lain yang tidak memengaruhi deklarasi variabel:
let n: number; n = <any>setTimeout(function () { /* snip */ }, 500);
Juga, harus dimungkinkan untuk menggunakan
window
objek secara eksplisit tanpaany
:let n: number; n = window.setTimeout(function () { /* snip */ }, 500);
sumber
window.setTimeout
) harus menjadi jawaban yang benar untuk pertanyaan ini karena ini adalah solusi paling jelas.any
tipe tersebut, Anda tidak benar-benar memberikan jawaban TypeScript.number
jenisnya akan menyebabkan kesalahan lint khusus TypeScript, karenasetTimeout
fungsinya memerlukan lebih dari itu.window.setTimeout
dapat menyebabkan masalah dengan kerangka pengujian unit (node.js). Solusi terbaik adalah dengan menggunakanlet n: NodeJS.Timeout
dann = setTimeout
.let timer: ReturnType<typeof setTimeout> = setTimeout(() => { ... }); clearTimeout(timer);
Dengan menggunakan
ReturnType<fn>
Anda mendapatkan kemerdekaan dari platform. Anda tidak akan dipaksa untuk menggunakanany
atauwindow.setTimeout
yang akan rusak jika Anda menjalankan kode tanpa server nodeJS (mis. Halaman yang dirender sisi server).Kabar baiknya, ini juga kompatibel dengan Deno!
sumber
setTimeout
/clearTimeout
dan tidak digunakanany
.NodeJS.Timeout
jika menggunakansetTimeout
secara langsung dannumber
jika menggunakanwindow.setTimeout
. Tidak perlu digunakanReturnType
.setTimeout
fungsi dan mengharapkan hasilnya disimpan dalam variabel. Coba sendiri di playground TS.setTimeout
salah (karena alasan yang tidak dapat dijelaskan oleh siapa pun) tetapi setidaknya solusi ini harus menutupi itu dengan cara yang sedikit lebih baik daripada hanya menggunakanany
.Saya kira itu tergantung di mana Anda akan menjalankan kode Anda.
Jika target waktu proses Anda adalah Node JS sisi server, gunakan:
let timeout: NodeJS.Timeout; global.clearTimeout(timeout);
Jika target waktu proses Anda adalah browser, gunakan:
let timeout: number; window.clearTimeout(timeout);
sumber
Ini kemungkinan akan bekerja dengan versi yang lebih lama, tetapi dengan versi TypeScript
^3.5.3
dan versi Node.js^10.15.3
, Anda harus dapat mengimpor fungsi khusus Node dari modul Timers , yaitu:import { setTimeout } from 'timers';
Itu akan mengembalikan instance dari tipe Timeout
NodeJS.Timeout
yang dapat Anda teruskan keclearTimeout
:import { clearTimeout, setTimeout } from 'timers'; const timeout: NodeJS.Timeout = setTimeout(function () { /* snip */ }, 500); clearTimeout(timeout);
sumber
setTimeout
, sesuatu seperticonst { setTimeout } = window
akan menghapus kesalahan tersebut.Saya menghadapi masalah yang sama dan solusi yang diputuskan oleh tim kami untuk digunakan, hanya menggunakan "apa saja" untuk jenis pengatur waktu. Misalnya:
let n: any; n = setTimeout(function () { /* snip */ }, 500);
Ini akan bekerja dengan kedua implementasi metode setTimeout / setInterval / clearTimeout / clearInterval.
sumber
window.setTimeout
mungkin tidak bekerja dengan kerangka pengujian unit. Ada tipe yang bisa digunakan disini .. IniNodeJS.Timeout
. Anda mungkin berpikir Anda tidak berada dalam lingkungan node tetapi saya punya berita untuk Anda: Webpack / TypeScript dll. Sedang menjalankan node.js.Jika Anda ingin solusi nyata untuk skrip ketikan tentang pengatur waktu, ini dia:
Bug dalam jenis 'nomor' kembali itu bukan Timer atau apa pun.
Ini untuk solusi ketikan versi ~> 2.7:
Sekarang kita perbaiki semua, cukup nyatakan seperti ini:
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; } ... }
sumber
Jika Anda menargetkan
setInterval
dariwindow
. Kemudian Anda juga bisa menulisnya sebagailet timerId: number = setInterval((()=>{ this.populateGrid(true) }) as TimerHandler, 5*1000) }
sumber