¿Cómo se establece explícitamente una nueva propiedad en 'window' en TypeScript?


Configuro espacios de nombres globales para mis objetos estableciendo explícitamente una propiedad en window.

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

TypeScript subraya MyNamespace y se queja de que:

La propiedad 'MyNamespace' no existe en el valor de tipo 'window' cualquier"

Puedo hacer que el código funcione declarando MyNamespace como una variable ambiental y eliminando la explicitud window, pero no quiero hacer eso.

declare var MyNamespace: any;

MyNamespace = MyNamespace || {};

¿Cómo puedo mantener window allí y hacer feliz a TypeScript?

As una nota de lado, me resulta especialmente curioso que el Manuscrito se queja ya que me dice que window es de tipo any que por definitivamente puede contener cualquier cosa.

 284
Author: joshuapoehls, 2012-10-03

14 answers

Para mantenerlo dinámico, simplemente use:

(<any>window).MyNamespace
 288
Author: chinupson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-14 08:26:23

Acabo de encontrar la respuesta a esto en la respuesta de otra pregunta de StackOverflow.

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

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

Básicamente necesita extender la interfaz window existente para informarle sobre su nueva propiedad.

 288
Author: joshuapoehls,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-06-15 20:46:33

O...

Puedes escribir:

window['MyNamespace']

Y no obtendrás un error de compilación y funciona igual que escribir window.MyNamespace

 142
Author: Evan Larsen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-20 19:36:21

¿Usando TSX? Ninguna de las otras respuestas funcionaban para mí.

Esto es lo que hice:

(window as any).MyNamespace
 107
Author: David Boyd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-30 20:13:03

La respuesta aceptada es la que solía usar, pero con TypeScript 0.9.* ya no funciona. La nueva definición de la interfaz Window parece reemplazar completamente la definición incorporada, en lugar de aumentarla.

He empezado a hacer esto en su lugar:

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

declare var window: MyWindow;

ACTUALIZACIÓN: Con TypeScript 0.9.5 la respuesta aceptada está funcionando de nuevo.

 50
Author: Blake Mitchell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-20 18:37:49

Si necesita extender el objeto window con un tipo personalizado que requiera el uso de import puede usar el siguiente método:

Ventana.d. ts

import MyInterface from './MyInterface';

declare global {
    interface Window {
        propName: MyInterface
    }
}

Véase 'Aumento Global' en la sección 'Fusión de Declaraciones' del Manual: https://www.typescriptlang.org/docs/handbook/declaration-merging.html#global-augmentation

 30
Author: Lucifer Sam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-23 15:24:04

Global son "malos":), creo que la mejor manera de tener también la portabilidad es:

Primero exportas la interfaz: (eg:./personalizar.ventana.ts)

export interface CustomWindow extends Window {
    customAttribute: any;
}

Segundo importa

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

Tercera ventana var global con ventana personalizada

declare let window: CustomWindow;

De esta manera no tienes también una línea roja en un IDE diferente si la usas con atributos existentes del objeto window, así que al final intenta:

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

Probado con Typescript 2.4.x

 22
Author: onalbi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-26 10:49:34

Aquí le mostramos cómo hacerlo, si está utilizando TypeScript Definition Manager!

npm install typings --global

Crear typings/custom/window.d.ts:

interface Window {
  MyNamespace: any;
}

declare var window: Window;

Instale su escritura personalizada:

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

Hecho, úsalo! Typescript ya no se quejará:

window.MyNamespace = window.MyNamespace || {};
 8
Author: Nik Sumeiko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-19 21:31:52

La mayoría de las otras respuestas no son perfectas.

  • Algunos de ellos simplemente suprimen la inferencia de tipo para shop.
  • Algunos de los otros solo se preocupan por la variable global como espacio de nombres, pero no como interfaz/clase

También me encuentro con un problema similar esta mañana. Probé tantas "soluciones" en SO, pero ninguna de ellas produce ningún error de tipo absolutamente y habilita la activación de salto de tipo en IDE(webstorm o vscode).

Finalmente, desde aquí

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

, encuentro una solución razonable para adjuntar tipos para la variable global que actúa como interfaz/clase y espacio de nombres tanto.

Ejemplo a continuación:

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

declare interface MyNamespace {
    somemethod?()
}

declare namespace MyNamespace {
    // ...
}

Ahora, el código anterior fusiona los tipos de espacio de nombres MyNamespace e interfaz MyNamespace en la variable global myNamespace(la propiedad de window).

 8
Author: e-cloud,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-19 03:26:24

No necesito hacer esto muy a menudo, el único caso que he tenido fue cuando uso Redux Devtools con middleware.

Simplemente lo hice:

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

O podrías hacer:

let myWindow = window as any;

Y luego myWindow.myProp = 'my value';

 7
Author: Dimitar Nikovski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-13 08:27:20

Si está utilizando la Angular CLI es realmente sencillo (probado en CLI RC.0):

Src/polyfills.ts

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

My-custom-utils.ts

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

Estoy usando IntelliJ, así que también tuve que cambiar la siguiente configuración en el IDE antes de que mi nuevo polyfills recogiera:

> File 
> Settings 
> Languages & Frameworks 
> TypeScript 
> check 'Use TypeScript Service'.
 5
Author: Stephen Paul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-22 06:28:26

Para referencia (esta es la respuesta correcta):

Dentro de un archivo de definición .d.ts

type MyGlobalFunctionType = (name: string) => void

Si trabaja en el navegador, usted agrega miembros al contexto de la ventana del navegador reabriendo la interfaz de la ventana:

interface Window {
  myGlobalFunction: MyGlobalFunctionType
}

La misma idea para NodeJS:

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

Ahora declaras la variable raíz (que realmente vivirá en window o global)

declare const myGlobalFunction: MyGlobalFunctionType;

Luego en un archivo regular .ts, pero importado como efecto secundario, realmente lo implementa:

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

Y finalmente usar en otra parte de la base de código, con:

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

myGlobalFunction("Kevin");
 3
Author: Benoit B.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-20 15:50:22

Después de encontrar respuestas, creo que esta página podría ser útil. https://www.typescriptlang.org/docs/handbook/declaration-merging.html#global-augmentation No estoy seguro sobre la historia de la fusión de declaraciones, pero explica por qué lo siguiente podría funcionar.

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

window.MyNamespace = window.MyNamespace || {};
 3
Author: Sheng,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-18 11:47:59

Hoy quería usar esto en una biblioteca de Angular (6) y me llevó un tiempo hacer que esto funcionara como esperaba.

Para que mi biblioteca usara declaraciones tuve que usar la extensión d.ts para el archivo que declara las nuevas propiedades del objeto global.

Así que al final, el archivo terminó con algo como:

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

Una vez creado, no olvides exponerlo en tu public_api.ts.

Eso lo hizo por mí. Espero que esto ayude.

 2
Author: Dirk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-01 11:29:02