TypeScript에서 `window`에 새 속성을 어떻게 명시적으로 설정합니까?
-
13-12-2019 - |
문제
명시적으로 속성을 설정하여 개체에 대한 전역 네임스페이스를 설정했습니다. window
.
window.MyNamespace = window.MyNamespace || {};
TypeScript 밑줄 MyNamespace
그리고 이렇게 불평합니다.
'mynamespace'속성은 '창'유형의 가치에 존재하지 않습니다.
다음을 선언하여 코드를 작동시킬 수 있습니다. MyNamespace
주변 변수로 사용하고 window
명확하지만 나는 그렇게 하고 싶지 않습니다.
declare var MyNamespace: any;
MyNamespace = MyNamespace || {};
어떻게 지킬 수 있나요? window
거기에 들어가서 TypeScript를 행복하게 만들까요?
부수적으로 TypeScript가 불평하는 것이 특히 재미있다고 생각합니다. window
유형이다 any
확실히 무엇이든 포함할 수 있습니다.
해결책
방금 이것에 대한 답을 찾았습니다. 다른 StackOverflow 질문의 답변.
declare global {
interface Window { MyNamespace: any; }
}
window.MyNamespace = window.MyNamespace || {};
기본적으로 기존을 확장해야합니다. window
새로운 속성에 대해 알려주는 인터페이스입니다.
다른 팁
동적으로 유지하려면 다음을 사용하세요.
(<any>window).MyNamespace
TYPESCRIPT ^3.4.3 기준으로 이 솔루션은 더 이상 작동하지 않습니다.
또는...
다음을 입력하면 됩니다:
window['MyNamespace']
컴파일 오류가 발생하지 않으며 입력하는 것과 동일하게 작동합니다. window.MyNamespace
TSX를 사용하시나요?다른 답변 중 어느 것도 나를 위해 일하지 않았습니다.
내가 한 일은 다음과 같습니다.
(window as any).MyNamespace
허용되는 답변은 제가 사용했던 답변이지만 TypeScript 0.9.*에서는 더 이상 작동하지 않습니다.의 새로운 정의 Window
인터페이스는 내장된 정의를 확장하는 대신 완전히 대체하는 것 같습니다.
나는 대신 이렇게 했습니다:
interface MyWindow extends Window {
myFunction(): void;
}
declare var window: MyWindow;
업데이트: TypeScript 0.9.5에서는 허용되는 답변이 다시 작동합니다.
글로벌은 "악"입니다. :) 이식성을 갖는 가장 좋은 방법은 다음과 같습니다.
먼저 인터페이스를 내보냅니다.(예:./custom.window.ts)
export interface CustomWindow extends Window {
customAttribute: any;
}
두 번째로 가져옵니다.
import {CustomWindow} from './custom.window.ts';
CustomWindow를 사용한 세 번째 캐스트 전역 변수 창
declare let window: CustomWindow;
이런 식으로 창 개체의 기존 속성과 함께 사용하는 경우 다른 IDE에도 빨간색 선이 없으므로 마지막에 다음을 시도하십시오.
window.customAttribute = 'works';
window.location.href = '/works';
Typescript 2.4.x 및 최신 버전으로 테스트되었습니다!
연장이 필요한 경우 window
다음을 사용해야 하는 사용자 정의 유형이 있는 객체 import
다음 방법을 사용할 수 있습니다.
window.d.ts
import MyInterface from './MyInterface';
declare global {
interface Window {
propName: MyInterface
}
}
핸드북의 '선언 병합' 섹션에서 '글로벌 확장'을 참조하세요. https://www.typescriptlang.org/docs/handbook/declaration-merging.html#global-augmentation
이 작업을 자주 수행할 필요는 없습니다. 제가 경험한 유일한 경우는 미들웨어와 함께 Redux Devtools를 사용할 때였습니다.
나는 간단히 이렇게 했습니다:
const composeEnhancers = (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
아니면 다음과 같이 할 수도 있습니다:
let myWindow = window as any;
그런 다음 myWindow.myProp = 'my value';
이용하시는 분들을 위해 각도 CLI 그것은 간단하다:
src/polyfills.ts
declare global {
interface Window {
myCustomFn: () => void;
}
}
내-사용자 정의-utils.ts
window.myCustomFn = function () {
...
};
IntelliJ를 사용하는 경우 새 폴리필을 선택하기 전에 IDE에서 다음 설정도 변경해야 합니다.
> File
> Settings
> Languages & Frameworks
> TypeScript
> check 'Use TypeScript Service'.
다른 답변의 대부분은 완벽하지 않습니다.
- 그 중 일부는 상점에 대한 유형 추론을 억제합니다.
- 다른 것 중 일부는 전역 변수를 네임스페이스로만 고려하고 인터페이스/클래스로는 고려하지 않습니다.
오늘 아침에도 비슷한 문제가 발생했습니다.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
(창의 속성).
주변에서 답변을 찾은 후 이 페이지가 도움이 될 것이라고 생각합니다.https://www.typescriptlang.org/docs/handbook/declaration-merging.html#global-augmentation선언 병합의 이력은 확실하지 않지만 다음이 작동할 수 있는 이유를 설명합니다.
declare global {
interface Window { MyNamespace: any; }
}
window.MyNamespace = window.MyNamespace || {};
사용하는 경우 방법은 다음과 같습니다. TypeScript 정의 관리자!
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 || {};
Typescript 3.x를 사용하는 경우 다음을 생략할 수 있습니다. declare global
다른 답변에 참여하고 대신 다음을 사용하십시오.
interface Window {
someValue: string
another: boolean
}
Typescript 3.3, WebPack 및 TSLint를 사용할 때 이것은 나와 함께 작동했습니다.
Typscript는 문자열 속성에 대한 유형 검사를 수행하지 않습니다.
window["newProperty"] = customObj;
이상적으로는 전역 변수 시나리오를 피해야 합니다.나는 가끔 브라우저 콘솔에서 개체를 디버깅하는 데 사용합니다.
참고로 (정답입니다):
내부 .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");
사용자 정의 인터페이스를 만들어 창을 확장하고 사용자 정의 속성을 선택 사항으로 추가하세요.
그런 다음 사용자 정의 인터페이스를 사용하지만 원래 창으로 평가되는 customWindow를 허용합니다.
typescript@3.1.3과 함께 작동합니다.
interface ICustomWindow extends Window {
MyNamespace?: any
}
const customWindow:ICustomWindow = window;
customWindow.MyNamespace = customWindow.MyNamespace {}
계산된 속성이나 동적 속성을 설정하려는 사람들을 위해 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]
나는 오늘 이것을 Angular(6) 라이브러리에서 사용하고 싶었고 이것이 예상대로 작동하도록 하는 데 시간이 걸렸습니다.
내 라이브러리에서 선언을 사용하려면 다음을 사용해야 했습니다. d.ts
전역 개체의 새 속성을 선언하는 파일의 확장자입니다.
결국 파일은 다음과 같이 끝났습니다.
/path-to-angular-workspace/angular-workspace/projects/angular-library/src/globals.d.ts
일단 생성되면 이를 귀하의 웹사이트에 노출시키는 것을 잊지 마십시오. public_api.ts
.
그것은 나를 위해 해냈습니다.도움이 되었기를 바랍니다.
먼저 현재 범위에서 창 개체를 선언해야 합니다.
TypeScript는 객체의 유형을 알고 싶어하기 때문입니다.
창 개체는 다른 곳에 정의되어 있으므로 다시 정의할 수 없습니다.
하지만 다음과 같이 선언할 수 있습니다.
declare var window: any;
이것은 창 개체를 재정의하지 않거나 이름이 있는 다른 변수를 생성하지 않습니다. window
.
이는 창이 다른 곳에 정의되어 있고 현재 범위에서 이를 참조하고 있음을 의미합니다.
그런 다음 다음과 같이 간단히 MyNamespace 개체를 참조할 수 있습니다.
window.MyNamespace
또는 새 속성을 설정할 수 있습니다. window
간단히 말해서 :-
window.MyNamespace = MyObject
이제 타이프스크립트는 불평하지 않을 것입니다.