टाइपस्क्रिप्ट - सेटटाइमआउट (नोड बनाम विंडो) के सही संस्करण का उपयोग करें


111

मैं नवीनतम संकलक संस्करण का उपयोग करने के लिए कुछ पुराने टाइपस्क्रिप्ट कोड को अपग्रेड करने पर काम कर रहा हूं, और मुझे कॉल करने में परेशानी हो रही है 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: 'टाइमर' टाइप करने के लिए 'टाइमर' टाइप करने योग्य नहीं है।


क्या आपके tsconfig.json में एक प्रकार: ["नोड"] है? देखें stackoverflow.com/questions/42940954/...
koe

@ नहीं, मेरे पास प्रकार नहीं हैं: ["नोड"] tsconfig फ़ाइल में विकल्प। लेकिन नोड प्रकार कुछ और के रूप में एक npm निर्भरता के रूप में खींचा जा रहा है।
केविन बाघे

1
आप tsconfig.json में "प्रकार" को स्पष्ट रूप से परिभाषित कर सकते हैं - जब आप "नोड" को छोड़ देते हैं तो इसका उपयोग संकलन में नहीं किया जाता है। जैसे "प्रकार": ["jQuery"]
कोए

1
यह आश्चर्य की बात है कि @koe ("प्रकार" विकल्प) के उत्तर में कोई वोट नहीं है, केवल सही सही उत्तर है।
ईगोर नेपोमनिस्चीह

जवाबों:


87

एक और वर्कअराउंड जो चर घोषणा को प्रभावित नहीं करता है:

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

इसके अलावा, windowवस्तु का उपयोग बिना स्पष्ट रूप से करना संभव होना चाहिए any:

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

25
मुझे लगता है कि window.setTimeoutइस प्रश्न के लिए अन्य एक ( ) सही उत्तर होना चाहिए क्योंकि यह सबसे स्पष्ट समाधान है।
Amik

5
यदि आप anyप्रकार का उपयोग कर रहे हैं , तो आप वास्तव में टाइपस्क्रिप्ट उत्तर नहीं दे रहे हैं।
एस ..

इसी तरह numberटाइप टाइपस्क्रिप्ट विशिष्ट लिंट त्रुटियों के लिए नेतृत्व करेंगे, क्योंकि setTimeoutफ़ंक्शन को इससे अधिक की आवश्यकता होती है।
एस ..

1
window.setTimeoutयूनिट टेस्ट फ्रेमवर्क (नोड.जेएस) के साथ समस्या हो सकती है। सबसे अच्छा समाधान का उपयोग let n: NodeJS.Timeoutऔर है n = setTimeout
cchamberlain

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

clearTimeout(timer);

उपयोग करने से ReturnType<fn>आपको मंच से स्वतंत्रता मिल रही है। आप का उपयोग करने के लिए मजबूर नहीं किया जाएगा anyऔर न ही window.setTimeoutजो होगा यदि आप कोड नहीं NodeJS सर्वर (उदा। सर्वर साइड गाया पेज) चलाने टूट गया।


अच्छी खबर, यह भी Deno के साथ संगत है!


9
मेरी समझ यह है कि यह सही उत्तर है और इसे स्वीकार किया जाना चाहिए, क्योंकि यह समर्थन करने वाले हर मंच के लिए सही प्रकार की परिभाषा प्रदान करता है setTimeout/ clearTimeoutऔर इसका उपयोग नहीं करता है any
afenster

11
यह समाधान है यदि आप एक पुस्तकालय लिख रहे हैं जो NodeJS और ब्राउज़र दोनों पर चलता है।
yqlim

रिटर्न प्रकार NodeJS.Timeoutयदि setTimeoutसीधे उपयोग कर रहा है और numberयदि उपयोग कर रहा है window.setTimeout। उपयोग करने की आवश्यकता नहीं होनी चाहिए ReturnType
cchamberlain

@cchamberlain आपको setTimeoutफ़ंक्शन चलाने के दौरान इसकी आवश्यकता है और इसके परिणाम को चर में संग्रहीत किए जाने की अपेक्षा कर रहे हैं। टीएस खेल के मैदान में खुद को आजमाएं।
Akxe

14

मुझे लगता है कि यह इस बात पर निर्भर करता है कि आप अपना कोड कहां चला रहे हैं।

यदि आपका रनटाइम लक्ष्य सर्वर साइड नोड JS है, तो उपयोग करें:

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

यदि आपका रनटाइम लक्ष्य एक ब्राउज़र है, तो उपयोग करें:

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

4

मुझे उसी समस्या का सामना करना पड़ा और हमारी टीम ने जिस वर्कअराउंड का उपयोग करने का फैसला किया, वह सिर्फ टाइमर प्रकार के लिए "किसी" का उपयोग करना था। उदाहरण के लिए:

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

यह setTimeout / setInterval / clearTimeout / clearInterval विधियों के कार्यान्वयन के साथ काम करेगा।


2
हाँ, यह काम करता है। मुझे यह भी एहसास हुआ कि मैं सीधे विंडो ऑब्जेक्ट पर विधि निर्दिष्ट कर सकता हूं: window.setTimeout (...)। यकीन नहीं है कि अगर यह सबसे अच्छा तरीका है, लेकिन मैं अभी इसके साथ रहना चाहता हूँ।
केविन बाघे

1
आप NodeJS नामस्थान टाइपस्क्रिप्ट में ठीक से आयात कर सकते हैं, यह उत्तर देखें ।
होवलाडल

वास्तव में प्रश्न का उत्तर देने के लिए ("मैं संकलक को मेरे द्वारा इच्छित संस्करण को लेने का निर्देश कैसे दे सकता हूं"), आप नीचे दिए गए @dhilt के अनुसार window.setTimeout () का उपयोग कर सकते हैं।
Anson VanDoren

window.setTimeoutइकाई परीक्षण चौखटे के साथ काम नहीं कर सकते। एक प्रकार है जिसका उपयोग यहां किया जा सकता है .. इसका NodeJS.Timeout। आप सोच सकते हैं कि आप एक नोड वातावरण में नहीं हैं, लेकिन मेरे पास आपके लिए समाचार हैं: वेबपैक / टाइपस्क्रिप्ट आदि नोड.जेएस निष्पादित कर रहे हैं।
cchamberlain

4

यह पुराने संस्करणों के साथ काम करने की संभावना है, लेकिन टाइपस्क्रिप्ट संस्करण ^3.5.3और Node.js संस्करण के साथ ^10.15.3, आपको टाइमर मॉड्यूल से नोड-विशिष्ट कार्यों को आयात करने में सक्षम होना चाहिए , अर्थात:

import { setTimeout } from 'timers';

उस प्रकार के टाइमआउट का एक उदाहरण लौटाएगा NodeJS.Timeoutजिसे आप पास कर सकते हैं clearTimeout:

import { clearTimeout, setTimeout } from 'timers';

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

clearTimeout(timeout);

1
इसी तरह, यदि आप ब्राउज़र संस्करण चाहते हैं, तो setTimeoutऐसा कुछ const { setTimeout } = windowउन त्रुटियों को स्पष्ट करेगा।
जैक स्टीम

1
  • अगर आप यहां जाने वाले समय के बारे में टाइपस्क्रिप्ट के लिए वास्तविक समाधान चाहते हैं:

    बग रिटर्न प्रकार 'संख्या' में है यह टाइमर या कुछ और नहीं है।

    यह अनुलेखन संस्करण ~> 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;
   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;
         }

     ...
     }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.