webkiturl - Como você explicitamente define uma nova propriedade em `window` no TypeScript?




window webkiturl typescript (12)

Eu configurei namespaces globais para meus objetos definindo explicitamente uma propriedade na window .

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

TypeScript sublinha MyNamespace e reclama que:

A propriedade 'MyNamespace' não existe no valor do tipo 'window' any "

Eu posso fazer o código funcionar declarando MyNamespace como uma variável de ambiente e descartando a explicitação da window mas não quero fazer isso.

declare var MyNamespace: any;

MyNamespace = MyNamespace || {};

Como posso manter a window lá e tornar o TypeScript feliz?

Como uma nota lateral, acho especialmente engraçado que o TypeScript reclame, pois me diz que a window é do tipo any que definitivamente pode conter qualquer coisa.


A maioria das outras respostas não é perfeita.

  • Alguns deles apenas suprimem a inferência de tipos para a loja.
  • Alguns dos outros só se importam com variáveis ​​globais como namespace, mas não como interface / classe

Eu também encontro o problema semelhante esta manhã. Eu tentei tantas "soluções" no SO, mas nenhuma delas produziu nenhum tipo de erro e habilitar o acionamento de tipos de saltos no IDE (webstorm ou vscode).

Finalmente, daqui

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

, Eu acho uma solução razoável para anexar tipings para variável global que atua como interface / classe e namespace ambos .

Exemplo está abaixo:

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

declare interface MyNamespace {
    somemethod?()
}

declare namespace MyNamespace {
    // ...
}

Agora, o código acima mescla os tipos de namespace MyNamespace e interface MyNamespace na variável global myNamespace (a propriedade da janela).


A resposta aceita é o que eu costumava usar, mas com o TypeScript 0.9. * Não funciona mais. A nova definição da interface Window parece substituir completamente a definição interna, em vez de aumentá-la.

Eu comecei a fazer isso em vez disso:

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

declare var window: MyWindow;

ATUALIZAÇÃO: Com o TypeScript 0.9.5, a resposta aceita está funcionando novamente.


Crie uma interface personalizada para estender a janela e adicione sua propriedade personalizada como opcional.

Em seguida, deixe o customWindow que usa a interface personalizada, mas valorizada com a janela original.

Trabalhou com o [email protected]

interface ICustomWindow extends Window {
  MyNamespace?: any
}

const customWindow:ICustomWindow = window;

customWindow.MyNamespace = customWindow.MyNamespace {} 


Eu queria usar isso em uma biblioteca Angular (6) hoje e levei um tempo para que isso funcionasse como esperado.

Para que minha biblioteca use declarações eu tive que usar a extensão d.ts para o arquivo que declara as novas propriedades do objeto global.

Então, no final, o arquivo acabou com algo como:

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

Uma vez criado, não se esqueça de expô-lo em seus public_api.ts .

Isso fez isso por mim. Espero que isto ajude.


Global é "mal" :), acho que a melhor maneira de ter também a portabilidade é:

Primeiro você exporta a interface: (por exemplo: ./custom.window.ts)

export interface CustomWindow extends Window {
    customAttribute: any;
}

Segundo você importa

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

Terceira janela global de cast do tipo var com CustomWindow

declare let window: CustomWindow;

Desta forma, você não tem também a linha vermelha no IDE diferente, se você usar com atributos existentes do objeto de janela, então no final tente:

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

Testado com o Typescript 2.4.x


Para aqueles que desejam definir uma propriedade computada ou dinâmica no objeto window , você verá que isso não é possível com o método declare global . Para esclarecer este caso de uso

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

Você pode tentar fazer algo assim

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

O acima será erro embora. Isso ocorre porque, em Typescript, as interfaces não funcionam bem com as propriedades calculadas e lançam um erro como

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

Para contornar isso, você pode ir com a sugestão de lançar a window para <any> para que você possa fazer

(window as any)[DynamicObject.key]

Para mantê-lo dinâmico, basta usar:

(<any>window).MyNamespace

Se você estiver usando o Angular CLI , é muito simples:

src / polyfills.ts

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

my-custom-utils.ts

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

Se você estiver usando o IntelliJ, também é necessário alterar a configuração a seguir no IDE antes que os novos polyfills sejam selecionados:

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

Se você estiver usando o Typescript 3.x, poderá omitir a parte declare global nas outras respostas e, em vez disso, use apenas:

interface Window {
  someValue: string
  another: boolean
}

Isso funcionou comigo ao usar o Typescript 3.3, WebPack e TSLint.


Usando o TSX? Nenhuma das outras respostas estava funcionando para mim.

Aqui está o que eu fiz:

(window as any).MyNamespace

Veja como fazer isso, se você estiver usando o TypeScript Definition Manager !

npm install typings --global

Crie typings/custom/window.d.ts :

interface Window {
  MyNamespace: any;
}

declare var window: Window;

Instale sua digitação personalizada:

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

Feito, use it ! O typescript não vai mais reclamar:

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




typescript