TypeScript-올바른 버전의 setTimeout 사용 (노드 대 창)


115

최신 컴파일러 버전을 사용하기 위해 이전 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 : '타이머'유형은 '번호'유형에 할당 할 수 없습니다.


tsconfig.json에 유형 : [ "node"]가 있습니까? stackoverflow.com/questions/42940954/…
koe

@koe 아니요, tsconfig 파일에 types : [ "node"] 옵션이 없습니다. 그러나 노드 유형은 다른 것에 대한 npm 종속성으로 가져오고 있습니다.
Kevin Tighe

1
tsconfig.json에서 "types"를 명시 적으로 정의 할 수도 있습니다. "node"를 생략하면 컴파일에 사용되지 않습니다. 예 : "types": [ "jQuery"]
koe aug

1
@koe ( "types"옵션 사용)의 대답에는 투표가없고 유일한 정답 인 것은 놀랍습니다.
Egor Nepomnyaschih

@ KevinTighe의는 types포함되어 있지 않습니다 node하지만 setTimeout여전히 노드 유형보다는 브라우저 유형을 가져옵니다. types모든 유형의 기본값 node_modules/@types에 설명 된대로 typescriptlang.org/tsconfig#types , 그러나 당신이 경우에도 이렇게 지정 types하고 있지 않는"node", 이유는 무엇입니까 setTimeout여전히 노드의 유형을 얻는 방법 브라우저 유형을받을 수 있나요? @Axke의 솔루션은 기본적으로 반환되는 것을 반환한다고 말하는 약간의 해킹입니다. TypeScript는 여전히 잘못된 유형을 찾을 수 있지만 적어도 지속적으로 잘못됩니다.
Denis Howe

답변:


88

변수 선언에 영향을주지 않는 또 다른 해결 방법 :

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유형을 사용하는 경우 실제로 TypeScript 답변을 제공하지 않습니다.
S ..

마찬가지로 함수에 더 많은 것이 필요하므로 number유형은 TypeScript 특정 린트 오류로 이어 setTimeout집니다.
S ..

1
window.setTimeout단위 테스트 프레임 워크 (node.js)에 문제가 발생할 수 있습니다. 가장 좋은 해결책은 let n: NodeJS.Timeoutn = setTimeout.
cchamberlain

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

clearTimeout(timer);

사용함으로써 ReturnType<fn>당신은 플랫폼으로부터 독립을 얻고 있습니다. 당신이 사용하도록 강요되지 any않으며 window.setTimeout이는 당신은 코드 번호 nodeJS 서버 (예. 서버 측 렌더링 된 페이지)를 실행하면 휴식.


좋은 소식입니다. 이것은 Deno 와도 호환됩니다!


9
나의 이해는이 정답이며, 승인 된 것이어야한다, 그것은 모든 플랫폼을 지원하기위한 올바른 유형 정의를 제공하기 때문이다 setTimeout/ clearTimeout및 사용하지 않습니다 any.
afenster 19-06-25

11
이것은 NodeJS와 브라우저 모두에서 실행되는 라이브러리를 작성하는 경우 솔루션입니다.
yqlim

반환 유형은 직접 NodeJS.Timeout사용 setTimeout하는 number경우 와 window.setTimeout. 사용할 필요가 없습니다 ReturnType.
cchamberlain

@cchamberlain setTimeout함수 를 실행 하고 그 결과가 변수에 저장되기를 기대할 때 필요합니다. TS 놀이터에서 직접 시도해보십시오.
Akxe

OP와 나를 위해 TypeScript는 setTimeout잘못된 유형을 얻지 만 (아무도 설명 할 수없는 이유로) 적어도이 솔루션 은를 사용하는 것보다 약간 더 나은 방법으로 그것을 가려야합니다 any.
Denis Howe

15

코드를 실행할 위치에 따라 다릅니다.

런타임 대상이 서버 측 Node JS 인 경우 다음을 사용하십시오.

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

런타임 대상이 브라우저 인 경우 다음을 사용하십시오.

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

5

이는 이전 버전에서 작동 할 가능성이 있지만 TypeScript 버전 ^3.5.3및 Node.js 버전 ^10.15.3에서는 Timers 모듈 에서 노드 별 함수를 가져올 수 있습니다 . 예 :

import { setTimeout } from 'timers';

그러면 전달할 수 있는 유형 의 Timeout 인스턴스가 반환 NodeJS.Timeout됩니다 clearTimeout.

import { clearTimeout, setTimeout } from 'timers';

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

clearTimeout(timeout);

1
마찬가지로의 브라우저 버전을 원하는 경우 setTimeout다음과 같이 const { setTimeout } = window오류를 해결합니다.
Jack Steam

4

나는 동일한 문제에 직면했고 우리 팀이 사용하기로 결정한 해결 방법은 타이머 유형에 "any"를 사용하는 것입니다. 예 :

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

setTimeout / setInterval / clearTimeout / clearInterval 메소드의 두 구현 모두에서 작동합니다.


2
네, 작동합니다. 또한 창 개체에 직접 window.setTimeout (...) 메서드를 지정할 수 있다는 것도 깨달았습니다. 이것이 최선의 방법인지 확실하지 않지만 지금은 계속하겠습니다.
Kevin Tighe

1
typescript에서 NodeJS 네임 스페이스를 올바르게 가져올 수 있습니다 . 이 답변을 참조하십시오 .
hlovdal

실제로 질문에 답하려면 ( "내가 원하는 버전을 선택하도록 컴파일러에 지시 할 수있는 방법") 대신 window.setTimeout ()을 사용할 수 있습니다. @dhilt는 아래에 대답했습니다.
Anson VanDoren

window.setTimeout단위 테스트 프레임 워크에서는 작동하지 않을 수 있습니다. 여기에서 사용할 수있는 유형이 있습니다 .. 그것의 NodeJS.Timeout. 당신은 당신이 노드 환경에 있지 않다고 생각할 수 있지만 당신을위한 소식이 있습니다 : Webpack / TypeScript 등이 node.js를 실행하고 있습니다.
cchamberlain

1
  • 타이머에 대한 typescript에 대한 실제 솔루션을 원한다면 여기에 있습니다.

    버그는 반환 유형 'number'에 있으며 Timer 또는 다른 것이 아닙니다.

    이것은 typescripts 버전 ~> 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;
         }

     ...
     }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.