TypeScript - setTimeout'un doğru sürümünü kullanın (düğüm vs pencere)


135

En son derleyici sürümünü kullanmak için bazı eski TypeScript kodunu yükseltmeye çalışıyorum ve bir çağrı ile sorun yaşıyorum setTimeout. Kod, tarayıcının setTimeoutbir sayı döndüren işlevini çağırmayı bekler :

setTimeout(handler: (...args: any[]) => void, timeout: number): number;

Ancak, derleyici bunu bir NodeJS.Timer döndüren düğüm uygulamasına çözüyor:

setTimeout(callback: (...args: any[]) => void, ms: number, ...args: any[]): NodeJS.Timer;

Bu kod düğümde çalışmaz, ancak düğüm türleri başka bir şeye bağımlılık olarak çekilir (ne olduğundan emin değil).

Derleyiciye setTimeoutistediğim sürümü seçmesi için nasıl talimat verebilirim ?

İşte söz konusu kod:

let n: number;
n = setTimeout(function () { /* snip */  }, 500);

Bu, derleyici hatasını oluşturur:

TS2322: "Zamanlayıcı" türü, "sayı" türüne atanamaz.


Tsconfig.json dosyanızda bir tür: ["düğüm"] var mı? Stackoverflow.com/questions/42940954/… sayfasına
derkoe

@koe Hayır, tsconfig dosyasında şu türlere sahip değilim: ["node"] seçeneği. Ancak düğüm türleri, başka bir şeye npm bağımlılığı olarak çekiliyor.
Kevin Tighe

1
Ayrıca tsconfig.json'da "türler" i de açıkça tanımlayabilirsiniz - "düğümü" atladığınızda derlemede kullanılmaz. ör. "types": ["jQuery"]
derkoe

1
@Koe ("türler" seçeneğini kullanın) yanıtının herhangi bir oy içermemesi şaşırtıcıdır, tek doğru yanıt budur.
Egor Nepomnyaschih

@ KevinTighe types, içermez nodeancak setTimeouttarayıcı türü yerine Düğüm türünü almaya devam eder. typestüm türlere varsayılan node_modules/@typesaçıklandığı gibi, typescriptlang.org/tsconfig#types ama bile yapmak belirtmek typesve yok içerir "node", neden yok setTimeouthala Düğüm türünü olsun ve nasıl tarayıcı türü alabilirim? @ Axke'nin çözümü, temelde döndüğünü döndürdüğünü söyleyen bir hacklemedir. TypeScript hala yanlış türü buluyor olabilir, ancak en azından sürekli olarak yanlış olacaktır.
Denis Howe

Yanıtlar:


103

Değişken bildirimini etkilemeyen başka bir geçici çözüm:

let n: number;
n = <any>setTimeout(function () { /* snip */  }, 500);

Ayrıca, windownesneyi açık bir şekilde kullanmak mümkün olmalıdır.any :

let n: number;
n = window.setTimeout(function () { /* snip */  }, 500);

28
window.setTimeoutEn net çözüm olduğu için diğerinin ( ) bu soru için doğru cevap olması gerektiğini düşünüyorum.
amik

7
anyYazıyı kullanıyorsanız, gerçekten bir TypeScript cevabı vermiyorsunuz.
S ..

aynı şekilde numbertür, TypeScript'e özgü tüy bırakma hatalarına yol açar, çünkü setTimeoutişlev bundan fazlasını gerektirir.
S ..

3
window.setTimeoutbirim test çerçevelerinde (node.js) sorunlara neden olabilir. En iyi çözüm kullanmaktır let n: NodeJS.Timeoutve n = setTimeout.
cchamberlain

138
let timer: ReturnType<typeof setTimeout> = setTimeout(() => { ... });

clearTimeout(timer);

Kullanarak ReturnType<fn>platformdan bağımsızlık kazanırsınız. Sen kullanmak zorunda olmayacak any, ne de window.setTimeouthangi olacaktır kodu hiçbir nodeJS sunucusu (ör. Sunucu tarafı render sayfası) çalıştırırsanız bölünürler.


İyi haber, bu da Deno ile uyumlu!


11
Anladığım kadarıyla bu doğru cevaptır ve kabul edilen cevap olmalıdır, çünkü destekleyen setTimeout/ clearTimeoutkullanmayan her platform için doğru tip tanımını sağlar any.
afenster

12
Hem NodeJS hem de tarayıcıda çalışan bir kitaplık yazıyorsanız çözüm budur.
yqlim

1
Dönüş türü doğrudan NodeJS.Timeoutkullanılıyorsa setTimeoutve numberkullanılıyorsa şeklindedir window.setTimeout. Kullanmaya gerek yok ReturnType.
cchamberlain

@cchamberlain setTimeoutFonksiyonu çalıştırırken buna ihtiyacınız var ve sonucunun değişkende saklanmasını bekliyorsunuz. TS oyun alanında kendiniz deneyin.
Akxe

OP ve benim için TypeScript setTimeoutyanlış türden anlıyor (kimsenin açıklayamayacağı nedenlerden dolayı) ama en azından bu çözüm bunu kullanmaktan biraz daha iyi bir şekilde maskelemelidir any.
Denis Howe

16

Sanırım kodunuzu nerede çalıştıracağınıza bağlı.

Çalışma zamanı hedefiniz sunucu tarafı Node JS ise, şunu kullanın:

let timeout: NodeJS.Timeout;
global.clearTimeout(timeout);

Çalışma zamanı hedefiniz bir tarayıcıysa, şunu kullanın:

let timeout: number;
window.clearTimeout(timeout);

7

Bu muhtemelen eski sürümlerle çalışacaktır, ancak TypeScript sürümü ^3.5.3ve Node.js sürümü ile Düğüme ^10.15.3özgü işlevleri Zamanlayıcılar modülünden içe aktarabilmelisiniz , yani:

import { setTimeout } from 'timers';

Bu , geçebileceğiniz türdeki bir Zaman Aşımı örneğini döndürür :NodeJS.TimeoutclearTimeout

import { clearTimeout, setTimeout } from 'timers';

const timeout: NodeJS.Timeout = setTimeout(function () { /* snip */  }, 500);

clearTimeout(timeout);

2
Benzer şekilde, tarayıcı sürümünü istiyorsanız, setTimeoutbenzer bir şey const { setTimeout } = windowbu hataları düzeltir .
Jack Steam

2

Ben de aynı sorunla karşılaştım ve ekibimizin kullanmaya karar verdiği geçici çözüm, zamanlayıcı türü için "herhangi biri" kullanmaktı. Örneğin:

let n: any;
n = setTimeout(function () { /* snip */  }, 500);

SetTimeout / setInterval / clearTimeout / clearInterval yöntemlerinin her iki uygulamasıyla da çalışacaktır.


2
Evet, işe yarıyor. Ayrıca, yöntemi doğrudan pencere nesnesinde belirtebileceğimi de fark ettim: window.setTimeout (...). Bunun en iyi yol olup olmadığından emin değilim ama şimdilik buna bağlı kalacağım.
Kevin Tighe

1
NodeJS ad alanını typecript'te düzgün şekilde içe aktarabilirsiniz, bu yanıta bakın .
hlovdal

Soruyu gerçekten yanıtlamak için ("derleyiciye istediğim sürümü nasıl seçebilirim?"), @Dhilt aşağıda yanıtlandığı gibi bunun yerine window.setTimeout () kullanabilirsiniz.
Anson VanDoren

window.setTimeoutbirim test çerçeveleriyle çalışmayabilir. Burada kullanılabilecek bir tipi var .. Onun NodeJS.Timeout. Düğüm ortamında olmadığınızı düşünebilirsiniz ama size haberlerim var: Webpack / TypeScript vb. Node.js çalıştırıyor.
cchamberlain

0
  • Zamanlayıcılarla ilgili tipkript için gerçek bir çözüm istiyorsanız, buraya gidiyoruz:

    Hata dönüş türünde 'sayı', Zamanlayıcı veya başka bir şey değil.

    Bu, typcripts sürüm ~> 2.7 çözümü içindir:

export type Tick = null | number | NodeJS.Timer;

Şimdi hepsini düzelttik, şöyle ilan edin:

 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;
         }

     ...
     }

0

Eğer hedeflediğiniz setIntervalarasında window. O zaman şu şekilde de yazabilirsiniz:

let timerId: number = setInterval((()=>{
    this.populateGrid(true)
  }) as TimerHandler, 5*1000)
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.