TypeScript의`window`에서 새 속성을 어떻게 명시 적으로 설정합니까?


620

에 속성을 명시 적으로 설정하여 객체의 전역 네임 스페이스를 설정합니다 window.

window.MyNamespace = window.MyNamespace || {};

TypeScript는 다음을 강조 MyNamespace하고 다음과 같이 불평합니다.

'창 이름'유형의 값에 'MyNamespace'특성이 없습니다. "

MyNamespace주변 변수로 선언 하고 window명시 성을 삭제 하여 코드를 작동시킬 수 있지만 그렇게하고 싶지 않습니다.

declare var MyNamespace: any;

MyNamespace = MyNamespace || {};

어떻게 window거기에 머무르고 TypeScript를 행복하게 할 수 있습니까?

부수적으로 TypeScript는 그것이 무엇이든 포함 할 수있는 window유형 이라고 알려주기 때문에 TypeScript가 불평하는 것이 특히 재미 있다는 것을 알았습니다 any.


MHS

답변:


691

다른 StackOverflow question 's answer 에서 이에 대한 답변을 찾았습니다 .

declare global {
    interface Window { MyNamespace: any; }
}

window.MyNamespace = window.MyNamespace || {};

기본적으로 기존 window속성 을 확장 하여 새 속성에 대해 알려야합니다.


11
창에서 대문자 W를 주목하십시오. 저를 넘어 뜨 렸습니다.
ajm

2
tsc 1.0.1.0으로 컴파일 할 수 없었습니다. Blake Mitchell의 대답은 나를 위해 일했습니다.
Pat

43
이것은 별도의 .d.ts파일로 선언 된 경우에만 작동 합니다. .ts가져 오기 및 내보내기 자체를 사용 하는 파일 에서 사용될 때는 작동하지 않습니다 . 이 답변을 참조하십시오 .
cdauth

36
declare global { interface Window { ... } }타이프 라이터 2.5.2와 작품, 필요 .d.ts파일은 위에서 언급하지 않기 때문에
tanguy_k

2
처음에 typescript는 나에게 : error TS1234: An ambient module declaration is only allowed at the top level in a file.파일의 맨 위에 놓을 때 오류를 수정 했으므로 그렇게해야 할 수도 있습니다.
Zelphir Kaltstahl

397

동적으로 유지하려면 다음을 사용하십시오.

(<any>window).MyNamespace

9
tsx 파일 에서이 작업을 수행하는 방법에 대한 아이디어가 있습니까?
velop

2
@ martin : <any>는 명시 적으로 작동하므로 잘 작동합니다. 기타 : React 또는 다른 JSX 환경과 함께 Typescript를 사용하는 경우 (TSX 구문으로 결과) as대신 을 사용해야 합니다 <>. 아래 @ david-boyd의 답변을 참조하십시오 .
Don

31
MyNamespace
Arsalan Ahmad

마찬가지로 thisreturn (<any> this)['something in scope']
HankCa

1
나는 함께 그 라인에 해제 tslint에 있었다/* tslint:disable */
마이클 Yagudaev

197

TYPESCRIPT 기준 ^ 3.4.3이 솔루션은 더 이상 작동하지 않습니다

또는...

당신은 입력 할 수 있습니다 :

window['MyNamespace']

컴파일 오류가 발생하지 않으며 입력과 동일하게 작동합니다. window.MyNamespace


15
당신은 물론 한 경우하지만 당신은 아마 ... tslint 오류가 발생합니다
smnbbrv

69
이것은 TypeScript의 전체 아이디어 인 강력한 타이핑에 직면하여 완전히 날아갑니다.
d512

18
글로벌을 사용하는 @ user1334007도 마찬가지입니다. 그러나 일부 레거시 코드에는 필요합니다.
nathancahill 2016 년

3
@Ramesh window['MyNamespace']()(괄호 추가)
iBaff

6
"이것은 TypeScript의 전체 아이디어 인 강력한 타이핑에 직면하여 완전히 날아갑니다." 좋은!
Cody

188

TSX를 사용하십니까? 다른 답변들 중 어느 것도 나를 위해 일하지 않았습니다.

내가 한 일은 다음과 같습니다.

(window as any).MyNamespace


44
<any>타입 캐스트가 아닌 JSX로 해석 되기 때문에 TSX를 사용할 때를 제외하고는 동일 합니다.
Jake Boone

1
@David에게 감사드립니다. 이것은 새로운 Create React App 및 typescript 버전의 매력처럼 작동했습니다. 이전에 작동했습니다 : (<any> window) .MyNamespace, 그러나 이제 새로운 typescript 버전 3.5.x에서 깨지고 있습니다.
Jignesh Raval

어떤 창? 그렇다면 왜 typescript를 사용 하시겠습니까? Javascript x 만 사용)
MarcoLe

71

받아 들인 대답은 내가 사용했던 것이지만 TypeScript 0.9. *에서는 더 이상 작동하지 않습니다. Window인터페이스 의 새로운 정의는 기능 을 보강하는 대신 내장 정의를 완전히 대체하는 것으로 보입니다.

대신이 작업을 수행했습니다.

interface MyWindow extends Window {
    myFunction(): void;
}

declare var window: MyWindow;

업데이트 : TypeScript 0.9.5에서 허용되는 답변이 다시 작동합니다.


2
TypeScript 2.0.8에서 사용하는 모듈에서도 작동합니다. 예 : export default class MyClass{ foo(){ ... } ... } interface MyWindow extends Window{ mc: MyClass } declare var window: MyWindow window.mc = new MyClass() 그런 다음 Chrome Dev Tools 콘솔에서 다음과 같이 foo ()를 호출 할 수 있습니다. mc.foo()
Martin Majewski

글로벌로 무언가를 선언하고 싶지 않다면 이것은 매우 좋은 대답입니다. 반면에 필요한 declare var...모든 파일 을 호출 해야합니다.
Puce

이 경우 모노 레포에서 전역 창을 확장하는 다른 패키지와 충돌하지 않기 때문에이 방법에 대한 하나를 추가하십시오.
Dmitrii Sorin

감사합니다! 최고의 답변 IMO. 바닐라 창이 아니라는Window 사실을 무시해서는 안됩니다 . 형식 검사를 우회하거나 TS를 속이려하는 것만으로는 그렇게 할 수 없습니다.
Rutger Willems

불행히도 TS 3.6
부터는

65

글로벌은 "악"입니다 :), 또한 이식성을 갖는 가장 좋은 방법은 다음과 같습니다.

먼저 인터페이스를 내 보냅니다 (예 : ./custom.window.ts)

export interface CustomWindow extends Window {
    customAttribute: any;
}

두 번째로 수입

import {CustomWindow} from './custom.window.ts';

CustomWindow를 사용하여 세 번째 캐스트 전역 변수 창

declare let window: CustomWindow;

이런 식으로 window 객체의 기존 속성과 함께 사용하는 경우 다른 IDE에 빨간색 선이 없으므로 결국 시도하십시오.

window.customAttribute = 'works';
window.location.href = '/works';

Typescript 2.4.x 이상에서 테스트되었습니다!


1
왜 글로벌이 악한 지에 대해 확장하고 싶을 수도 있습니다. 우리의 경우에는 윈도우 객체에서 표준화되지 않은 API를 사용하고 있습니다. 현재는 폴리 필입니다. 정말 악한가요?
Mathijs Segers

1
@MathijsSegers 나는 특히 당신의 경우를 모르지만 ... 글로벌에 대한 악은 자바 스크립트에 관한 것이 아니라 모든 언어에 있습니다 .. 어떤 이유는 다음과 같습니다.-당신은 잘 디자인 패턴을 적용 할 수 없습니다-메모리 및 성능 문제 (You 어디서나 가지고, String Object에 무언가를 첨부하고 새로운 String을 수행 할 때 어떤 일이 발생하는지 확인하십시오.)-이름 충돌로 인해 코드에 부작용이 발생합니다. (특히 비동기 특성을 가진 Javascript에서) 계속할 수는 있지만 이미지를 만들 수 있다고 생각합니다 휴식 ...
onalbi

1
@onabi 문자 그대로 브라우저의 기능에 대해 이야기하고 있습니다. 브라우저이기 때문에 전 세계적으로 사용 가능합니다. 당신은 정말로 글로벌 정의로가는 것이 여전히 잘못되었다고 제안 할 것입니까? Ponyfills를 구현할 수는 있지만 실제로는 기능을 지원하는 브라우저를 부 풀릴 수 있습니다 (예 : 전체 화면 API). 나는 모든 세계가 사악한 박해라고 믿지 않는다고 말했다.
Mathijs Segers

2
@MathijsSegers 내 의견으로는 전역 변수는 우리가 사용할 수있는 곳에서 사용하거나 수정하지 않아야합니다 .. 브라우저가 존재하기 때문에 창을 사용할 수 있지만 항상 변이 된 것도 사실입니다 .. 예를 들어 지금 정의하면 window.feature = '기능'; 그리고 이것은 코드에서 방대한 방식으로 사용됩니다. window.feature가 모든 코드에서 브라우저에 의해 추가되면이 기능은 무시됩니다. 어쨌든 나는 내 문장에 대한 설명을 당신에게 반하지 않습니다.
onalbi


43

Angular CLI를 사용하는 사람들에게는 간단합니다.

src / polyfills.ts

declare global {
  interface Window {
    myCustomFn: () => void;
  }
}

my-custom-utils.ts

window.myCustomFn = function () {
  ...
};

IntelliJ를 사용하는 경우 새 폴리 필을 가져 오기 전에 IDE에서 다음 설정을 변경해야합니다.

> File 
> Settings 
> Languages & Frameworks 
> TypeScript 
> check 'Use TypeScript Service'.

1
declare global속임수이며,이 답변은 Angular CLI에만 국한되지 않습니다 ...
Avindra Goolcharan

31

이 작업을 자주 수행 할 필요는 없습니다. 미들웨어와 함께 Redux Devtools를 사용할 때 유일한 경우였습니다.

나는 단순히했다 :

const composeEnhancers = (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

아니면 할 수 있습니다 :

let myWindow = window as any;

그리고 myWindow.myProp = 'my value';


1
-이 경우 당신은 또한 NPM의 모든 정의가 포함 된 패키지를 설치할 수 있습니다 워드 프로세서에 지정된대로
bbrinx

당신이 할 수 있지만, 그것은 질문에 대한 답변이 아니라 해결 방법입니다
Vitalij

이 덕분에, 내가 사용하여 제대로 타이프에서 REDUX 도구를 가능하게 할 수 .__ REDUX_DEVTOOLS_EXTENSION__ && (창을 어느 등) (윈도우 같은) .__ REDUX_DEVTOOLS_EXTENSION __ ())
danivicario

20

다른 답변의 대부분은 완벽하지 않습니다.

  • 그들 중 일부는 상점의 유형 유추를 억제합니다.
  • 다른 것들 중 일부는 네임 스페이스로서의 전역 변수에만 관심이 있지만 인터페이스 / 클래스는 아닙니다.

오늘 아침에도 비슷한 문제가 발생합니다. SO에서 너무 많은 "솔루션"을 시도했지만 그중 어느 것도 절대 유형 오류가 발생하지 않으며 IDE (webstorm 또는 vscode)에서 유형 점프 트리거링을 활성화하지 않습니다.

마지막으로 여기에서

https://github.com/Microsoft/TypeScript/issues/3180#issuecomment-102523512

인터페이스 / 클래스 및 네임 스페이스 역할을하는 전역 변수에 대한 입력첨부 하는 합리적인 솔루션을 찾았습니다. .

예는 다음과 같습니다.

// typings.d.ts
declare interface Window {
    myNamespace?: MyNamespace & typeof MyNamespace
}

declare interface MyNamespace {
    somemethod?()
}

declare namespace MyNamespace {
    // ...
}

위의 코드는 네임 스페이스 MyNamespace와 인터페이스 MyNamespace의 입력을 전역 변수 myNamespace(창의 속성)에 병합합니다 .


2
감사합니다-이것은 주변 비 모듈 컨텍스트에서 사용할 수있는 유일한 것입니다.
Tyler Sebastian


13

TypeScript Definition Manager를 사용하는 경우이를 수행하는 방법은 다음과 같습니다 .

npm install typings --global

작성 typings/custom/window.d.ts:

interface Window {
  MyNamespace: any;
}

declare var window: Window;

사용자 정의 입력을 설치하십시오.

typings install file:typings/custom/window.d.ts --save --global

완료 하세요! Typescript는 더 이상 불평하지 않습니다.

window.MyNamespace = window.MyNamespace || {};

1
FWIW typings는 Typescript 2.0 (2016 년 중반)으로 폐기되었으며 소유자가 보관했습니다.
mrm

13

Typscript는 문자열 속성에 대한 유형 검사를 수행하지 않습니다.

window["newProperty"] = customObj;

이상적으로는 전역 변수 시나리오를 피해야합니다. 때로는 브라우저 콘솔에서 객체를 디버깅하는 데 사용합니다.



8

Typescript 3.x를 사용하는 경우 declare global다른 답변에서 해당 부분 을 생략 하고 대신 다음을 사용할 수 있습니다.

interface Window {
  someValue: string
  another: boolean
}

Typescript 3.3, WebPack 및 TSLint를 사용할 때 나와 함께 일했습니다.


에서 작동하지 않습니다 ^3.4.3. 이 답변은 저에게
Green

7

참고로 (정답입니다) :

.d.ts정의 파일 내부

type MyGlobalFunctionType = (name: string) => void

브라우저에서 작업하는 경우 Window 인터페이스를 다시 열어 브라우저의 창 컨텍스트에 멤버를 추가하십시오.

interface Window {
  myGlobalFunction: MyGlobalFunctionType
}

NodeJS에 대한 동일한 아이디어 :

declare module NodeJS {
  interface Global {
    myGlobalFunction: MyGlobalFunctionType
  }
}

이제 루트 변수를 선언합니다 (실제로 창 또는 전역에 있음)

declare const myGlobalFunction: MyGlobalFunctionType;

그런 다음 일반 .ts파일에서 부작용으로 가져 오면 실제로 구현합니다.

global/* or window */.myGlobalFunction = function (name: string) {
  console.log("Hey !", name);
};

마지막으로 코드베이스의 다른 곳에서 사용하십시오.

global/* or window */.myGlobalFunction("Kevin");

myGlobalFunction("Kevin");

고마워, 이것은 내가 찾은 가장 좋은 예이며 잘 작동합니다.
Nick G.

6

사용자 정의 인터페이스가 창을 확장하고 사용자 정의 특성을 선택 사항으로 추가하십시오.

그런 다음 사용자 정의 인터페이스를 사용하지만 원래 창으로 값을 지정하는 customWindow를 사용하십시오.

typescript@3.1.3과 함께 작동했습니다.

interface ICustomWindow extends Window {
  MyNamespace?: any
}

const customWindow:ICustomWindow = window;

customWindow.MyNamespace = customWindow.MyNamespace {} 

5

window객체 에 계산 또는 동적 속성을 설정하려는 사람들에게는 declare global메소드로 불가능하다는 것을 알 수 있습니다 . 이 사용 사례를 명확히하려면

window[DynamicObject.key] // Element implicitly has an 'any' type because type Window has no index signature

이런 식으로 시도 할 수 있습니다

declare global {
  interface Window {
    [DyanmicObject.key]: string; // error RIP
  }
}

위의 오류는 발생합니다. 이것은 Typescript에서 인터페이스가 계산 된 속성과 잘 작동하지 않아서

A computed property name in an interface must directly refer to a built-in symbol

이 문제를 해결하기 위해, 당신은 주조의 제안으로 갈 수 window<any>당신이 할 수 있도록

(window as any)[DynamicObject.key]

3
2019
Qwerty

4

create-react-app v3.3을 사용하여 이것을 달성하는 가장 쉬운 방법 Window은 자동 생성 유형 을 확장하는 것입니다 react-app-env.d.ts.

interface Window {
    MyNamespace: any;
}

3

먼저 현재 범위에서 창 개체를 선언해야합니다.
typescript가 객체의 유형을 알고 싶어하기 때문입니다.
창 개체가 다른 곳에 정의되어 있으므로 재정의 할 수 없습니다.
그러나 다음과 같이 선언 할 수 있습니다.

declare var window: any;

이것은 창 개체를 재정의하지 않거나 name을 가진 다른 변수를 만들지 않습니다 window.
이것은 창이 다른 곳에 정의되어 있으며 현재 범위에서 참조하고 있음을 의미합니다.

그런 다음 간단히 다음과 같이 MyNamespace 객체를 참조 할 수 있습니다.

window.MyNamespace

또는 다음과 같이 window간단하게 객체 의 새 속성을 설정할 수 있습니다 .

window.MyNamespace = MyObject

그리고 이제 타이프 스크립트가 불평하지 않습니다.


어디에 window정의 되어 있는지 알고 싶은 유스 케이스를 알고 있습니까?
Mav55

2

오늘 Angular (6) 라이브러리에서 이것을 사용하고 싶었고 예상대로 작동하는 데 시간이 걸렸습니다.

내 라이브러리가 선언을 사용하려면 d.ts 하려면 전역 객체의 새로운 속성을 선언하는 파일 확장자 .

결국 파일은 다음과 같이 끝났습니다.

/path-to-angular-workspace/angular-workspace/projects/angular-library/src/globals.d.ts

일단 생성되면, 그것을 노출시키는 것을 잊지 마십시오 public_api.ts .

그것은 나를 위해 그것을했다. 도움이 되었기를 바랍니다.

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