Como você definir explicitamente uma nova propriedade em `janela` na Máquina de escrever?
-
13-12-2019 - |
Pergunta
Eu configuração de espaços de nomes globais para meus objetos definindo explicitamente uma propriedade em window
.
window.MyNamespace = window.MyNamespace || {};
Transcrito sublinha MyNamespace
e queixa-se de que:
A propriedade 'MyNamespace' não existe no valor do tipo 'janela' qualquer"
Eu posso fazer o código funcionar, declarando MyNamespace
como uma variável de ambiente e soltando o window
explicitação mas eu não quero fazer isso.
declare var MyNamespace: any;
MyNamespace = MyNamespace || {};
Como posso manter window
lá e fazer o TypeScript feliz?
Como uma nota lateral acho que é especialmente engraçado que o TypeScript reclama, pois diz-me que window
é do tipo any
que por definitivamente pode conter qualquer coisa.
Solução
Só encontrei a resposta para isso em outro StackOverflow pergunta a resposta.
declare global {
interface Window { MyNamespace: any; }
}
window.MyNamespace = window.MyNamespace || {};
Basicamente o que você precisa estender o existente window
interface para dizer a ele sobre sua nova propriedade.
Outras dicas
Para mantê-lo dinâmico, basta usar:
(<any>window).MyNamespace
COMO O TYPESCRIPT ^3.4.3 ESTA SOLUÇÃO NÃO FUNCIONA MAIS
Ou...
você pode simplesmente digitar:
window['MyNamespace']
e você não vai obter um erro de compilação e funciona mesmo como escrever window.MyNamespace
Usando TSX?Nenhuma das outras respostas foram trabalhar para mim.
Aqui está o que eu fiz:
(window as any).MyNamespace
A resposta é aceite que eu costumava usar, mas com TypeScript 0.9.* ele não funciona mais.A nova definição do Window
interface parece substituir completamente a definição interna, em vez de aumentar a ele.
Passei a fazer isso:
interface MyWindow extends Window {
myFunction(): void;
}
declare var window: MyWindow;
ATUALIZAÇÃO: Com TypeScript 0.9.5 aceitos resposta está funcionando novamente.
Global são "do mal" :), acho que a melhor maneira de ter, também, a portabilidade é:
Primeiro você exporta a interface:(por exemplo:./personalizado.janela.ts)
export interface CustomWindow extends Window {
customAttribute: any;
}
Segundo importar
import {CustomWindow} from './custom.window.ts';
Terceiro elenco global var janela com CustomWindow
declare let window: CustomWindow;
Desta forma, você não tem também a linha vermelha em diferentes IDE se você usar com a existente atributos de objeto de janela, de modo que no final tentar:
window.customAttribute = 'works';
window.location.href = '/works';
Testado com Typescript 2.4.x e mais novo!
Se você precisa estender o window
objeto com um tipo personalizado que não requer o uso de import
você pode usar o seguinte método:
janela.d.ts
import MyInterface from './MyInterface';
declare global {
interface Window {
propName: MyInterface
}
}
Consulte "Global de Aumento' na 'Declaração de Fusão' secção do Manual: https://www.typescriptlang.org/docs/handbook/declaration-merging.html#global-augmentation
Eu não preciso fazer isso, muitas vezes, o único caso que eu tive foi quando usando Redux Devtools com o middleware.
Eu simplesmente fiz:
const composeEnhancers = (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
Ou você poderia fazer:
let myWindow = window as any;
e, em seguida, myWindow.myProp = 'my value';
Para aqueles que utilizam o Angular CLI é simples:
src/livros.ts
declare global {
interface Window {
myCustomFn: () => void;
}
}
meu-personalizado-utils.ts
window.myCustomFn = function () {
...
};
Se você estiver usando o IntelliJ, você também necessário alterar a seguinte configuração no IDE, antes de seus novos livros, de pegar:
> File
> Settings
> Languages & Frameworks
> TypeScript
> check 'Use TypeScript Service'.
A maioria das outras respostas não são perfeitos.
- Alguns deles simplesmente suprimir o tipo de inferência para a loja.
- Algumas pessoas só se preocupa com a variável global como espaço de nomes, mas não como interface/classe
Eu também encontrar o problema semelhante, esta manhã.Eu tentei tantas "soluções" sobre ISSO, mas nenhum deles produzem nenhum tipo de erro absolutamente e permitem acionar tipo de salto no IDE(webstorm ou vscode).
Finalmente, a partir daqui
https://github.com/Microsoft/TypeScript/issues/3180#issuecomment-102523512
, Eu encontrar uma solução razoável para anexar tipagens para a variável global que atua como interface/classe e de espaço de nomes de ambos.
Exemplo a seguir:
// typings.d.ts
declare interface Window {
myNamespace?: MyNamespace & typeof MyNamespace
}
declare interface MyNamespace {
somemethod?()
}
declare namespace MyNamespace {
// ...
}
Agora, o código acima mescla as tipagens de espaço de nomes MyNamespace
e interface MyNamespace
para a variável global myNamespace
(a propriedade da janela).
Depois de encontrar respostas, eu acho que esta página pode ser útil.https://www.typescriptlang.org/docs/handbook/declaration-merging.html#global-augmentation Não tenho certeza sobre o histórico de declaração de fusão, mas explica por que o seguinte pode trabalhar.
declare global {
interface Window { MyNamespace: any; }
}
window.MyNamespace = window.MyNamespace || {};
Aqui está como fazê-lo, se você estiver usando Transcrito De Definição De Gestor De!
npm install typings --global
Criar typings/custom/window.d.ts
:
interface Window {
MyNamespace: any;
}
declare var window: Window;
Instalação personalizada digitando:
typings install file:typings/custom/window.d.ts --save --global
Feito, usá-lo! O Typescript não reclamar mais:
window.MyNamespace = window.MyNamespace || {};
Se você estiver usando o Typescript 3.x, você pode ser capaz de omitir o declare global
parte em outras respostas e, em vez disso, basta usar:
interface Window {
someValue: string
another: boolean
}
Isso funcionou comigo quando utilizar o Typescript 3.3, WebPack e TSLint.
Typscript não executa tipo verificação nas propriedades de seqüência de caracteres.
window["newProperty"] = customObj;
Idealmente, a variável global cenário deve ser evitado.Eu uso às vezes para depurar um objeto no console do navegador.
De referência (esta é a resposta correta):
Dentro de um .d.ts
arquivo de definição de
type MyGlobalFunctionType = (name: string) => void
Se você trabalha no navegador, você pode adicionar membros a janela do navegador contexto de reabertura da Janela de interface:
interface Window {
myGlobalFunction: MyGlobalFunctionType
}
A mesma idéia para NodeJS:
declare module NodeJS {
interface Global {
myGlobalFunction: MyGlobalFunctionType
}
}
Agora você declarar a variável root (que vai realmente viver na janela ou global)
declare const myGlobalFunction: MyGlobalFunctionType;
Em seguida, em regular .ts
arquivo, mas importados como efeito colateral, você realmente implementá-lo:
global/* or window */.myGlobalFunction = function (name: string) {
console.log("Hey !", name);
};
E, finalmente usá-lo em outro lugar no codebase, com:
global/* or window */.myGlobalFunction("Kevin");
myGlobalFunction("Kevin");
Fazer uma interface personalizada estende-se a Janela e adicionar propriedades personalizadas como opcional.
Então, vamos a customWindow que usam a interface personalizada, mas valorizado com a janela original.
Ele trabalhou com o typescript@3.1.3.
interface ICustomWindow extends Window {
MyNamespace?: any
}
const customWindow:ICustomWindow = window;
customWindow.MyNamespace = customWindow.MyNamespace {}
Para aqueles que querem montar um computadas ou propriedade dinâmica no window
objeto, você verá que não é possível com os declare global
o método.Para esclarecer para 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 parecido com isso
declare global {
interface Window {
[DyanmicObject.key]: string; // error RIP
}
}
Acima de erro embora.Isso porque, no Typescript, interfaces de não jogar bem com propriedades calculadas e vai lançar um erro como
A computed property name in an interface must directly refer to a built-in symbol
Para contornar esse problema, você pode ir com a sugerir de fundição window
para <any>
assim, você pode fazer
(window as any)[DynamicObject.key]
Eu queria usar isso em um Angulares (6) biblioteca hoje e ele me levou um tempo para chegar a este funcionar como esperado.
Para a minha biblioteca, para uso de declarações que eu tinha que usar o d.ts
extensão para o arquivo, que declara que as novas propriedades do objeto global.
Então, no final, o arquivo terminou com algo como:
/path-to-angular-workspace/angular-workspace/projects/angular-library/src/globals.d.ts
Uma vez criada, não se esqueça de expô-lo no seu public_api.ts
.
Que ele fez por mim.Espero que isso ajude.
Primeiro você precisa declarar o objeto de janela no escopo atual.
Porque transcrito gostaria de saber o tipo do objeto.
Desde que o objeto da janela é definido em outro lugar você não pode redefini-la.
Mas você pode declará-lo como segue:-
declare var window: any;
Isso não vai redefinir o objeto de janela ou não vai criar outra variável com o nome window
.
Isso significa que a janela é definida em outro lugar, e você está apenas a referência a ele no escopo atual.
Em seguida, você pode consultar o seu MyNamespace objeto simplesmente:-
window.MyNamespace
Ou você pode definir uma nova propriedade em window
objeto simplesmente:-
window.MyNamespace = MyObject
E agora o typescript não vai reclamar.