Crea una variable global en TypeScript

92

En JavaScript, puedo hacer esto:

 something = 'testing';

Y luego en otro archivo:

 if (something === 'testing')

y se habrá somethingdefinido (siempre que se hayan llamado en el orden correcto).

Parece que no puedo averiguar cómo hacer eso en TypeScript.

Esto es lo que he probado.

En un archivo .d.ts:

interface Window { something: string; }

Luego, en mi archivo main.ts:

 window.something = 'testing';

luego en otro archivo:

 if (window.something  === 'testing')

Y esto funciona. Pero quiero poder perder una window.parte y somethingser global. ¿Hay alguna forma de hacer eso en TypeScript?

(En caso de que alguien esté interesado, realmente estoy tratando de configurar mi registro para mi aplicación. Quiero poder llamar log.Debugdesde cualquier archivo sin tener que importar y crear objetos).

Vaccano
fuente

Respuestas:

4

Bien, probablemente esto sea aún más feo que lo que hiciste, pero de todos modos ...

pero yo hago lo mismo entonces ...

Lo que puede hacer para hacerlo en TypeScript puro, es usar la evalfunción así:

declare var something: string;
eval("something = 'testing';")

Y luego podrás hacer

if (something === 'testing')

Esto no es más que un truco para forzar la ejecución de la instrucción sin que TypeScript se niegue a compilar, y nosotros declare varpara que TypeScript compile el resto del código.

tforgione
fuente
Esto no me funciona. Tengo eval ('myglobalvar = {};') ;. El resultado es: Error de referencia no detectado: myglobalvar no está definido en eval (eval en <anonymous> .....). Curiosamente, si lo ejecuto desde la consola, entonces funciona.
Ryan How
2
@DragonRock Probé Chrome y FF. Así que realmente no estoy seguro de lo que estaba pasando. De todas formas acabé haciendo declare var myglobalvar; (<cualquier> ventana) .myglobalvar = {}; Entonces puedo hacer referencia a él sin ventana después.
Ryan How
2
En su lugar, esto debería hacerse con un .d.tsarchivo de definición.
brianespinosa
2
Esto funciona para mí:export declare const SERVER = "10.1.1.26";
xinthose
2
evalSe desaconseja mucho el uso , por eso sugiero usar esta solución stackoverflow.com/a/56984504/5506278
Yaroslav Bai
62

Dentro de un .d.tsarchivo de definición

type MyGlobalFunctionType = (name: string) => void

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

interface Window {
  myGlobalFunction: MyGlobalFunctionType
}

Misma idea para NodeJS:

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

Ahora declara la variable raíz (que realmente vivirá en la ventana o global)

declare const myGlobalFunction: MyGlobalFunctionType;

Luego, en un .tsarchivo normal , pero importado como efecto secundario, realmente lo implementa:

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

Y finalmente úselo en otra parte del código base, con:

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

myGlobalFunction("Kevin");
Benoit B.
fuente
4
(Solo haciendo un comentario de pasada) ¡Habla sobre mucho trabajo para crear una variable global simple! lol
Pytth
6
@Benoit No obtengo la parte que dice "pero importada como efecto secundario". ¿Qué quieres decir con eso?. Intenté hacer esto, pero no me funciona, ¿podría compartir un ejemplo de código fuente?
BernalCarlos
Esto funciona bien para .tsarchivos, pero cuando lo uso window.myGlobalFunctionen mis .tsxarchivos, no es así. ¿Qué más necesito cambiar?
Kousha
13
¿Dónde coloca el archivo d.ts y cómo configura TypeScript para cargarlo?
Matthias
25

global Este es el futuro.

Primero, los archivos TypeScript tienen dos tipos de scopes

alcance global

Si su archivo no tiene ninguna línea importoexport , este archivo se ejecutará en el alcance global de que todas las declaraciones en él sean visibles fuera de este archivo.

Entonces crearíamos variables globales como esta:

// xx.d.ts
declare var age: number

// or 
// xx.ts
// with or without declare keyword
var age: number

// other.ts
globalThis.age = 18 // no error

Toda la magia viene de var. Reemplazar varcon leto constno funcionará.

alcance del módulo

Si su archivo tiene alguna línea importoexport , este archivo se ejecutará dentro de su propio alcance que necesitamos extender globalmente mediante la combinación de declaraciones .

// xx[.d].ts
declare global {
  var age: number;
}

// other.ts
globalThis.age = 18 // no error

Puede ver más sobre el módulo en los documentos oficiales.

edvard chen
fuente
Pero, ¿cómo harías esto sin el truco 'var'? Supongo que eso significa, ¿cómo haría el aumento de tipos en globalThis?
Tom
1
@Tom vares necesario. Pero puede simplemente declarar variable sin inicialización
edvard chen
Funcionó para mí (al menos por ahora) muchas gracias, deseo que esta respuesta suba. FYI: En mi caso, necesitaba agregar por // @ts-ignoreencima de la globalThislínea para el linter.
David
¿Cómo llamaría a la variable de edad en cualquier archivo mecanografiado?
Ashok kumar Ganesan
17

Así es como lo he solucionado:

Pasos:

  1. Declarado un espacio de nombres global, por ejemplo, custom.d.ts como se muestra a continuación:
declare global {
    namespace NodeJS {
        interface Global {
            Config: {}
        }
    }
}
export default global;
  1. Asigne el archivo creado anteriormente en "tsconfig.json" como se muestra a continuación:
"typeRoots": ["src/types/custom.d.ts" ]
  1. Obtenga la variable global creada anteriormente en cualquiera de los archivos de la siguiente manera:
console.log(global.config)

Nota:

  1. versión mecanografiada: "3.0.1".

  2. En mi caso, el requisito era establecer la variable global antes de iniciar la aplicación y la variable debería acceder a través de los objetos dependientes para que podamos obtener las propiedades de configuración necesarias.

¡Espero que esto ayude!

Gracias

Vikash Kumar Choudhary
fuente
14

Encontré una forma que funciona si uso JavaScript combinado con TypeScript.

logging.d.ts:

declare var log: log4javascript.Logger;

declaración de registro. js :

log = null;

initalize-app.ts

import './log-declaration.js';

// Call stuff to actually setup log.  
// Similar to this:
log = functionToSetupLog();

Esto lo coloca en el ámbito global y TypeScript lo sabe. Entonces puedo usarlo en todos mis archivos.

NOTA: Creo que esto solo funciona porque tengo la allowJsopción TypeScript configurada como verdadera.

Si alguien publica una solución pura de TypeScript, la aceptaré.

Vaccano
fuente
1
En su archivo initalize-app.ts puede usar: declare var log: any; Entonces no necesita tener el archivo d.ts o el archivo js. También puede reemplazar cualquiera con un tipo real o una definición de interfaz.
mattferderer
5

estoy usando solo esto

import {globalVar} from "./globals";
declare let window:any;
window.globalVar = globalVar;
Dima V
fuente
1
Esto elimina toda la información de tipo. También puede usar Javascript.
Timmmm
3

Pasé un par de horas para encontrar la manera adecuada de hacerlo. En mi caso, estoy tratando de definir la variable "log" global, por lo que los pasos fueron:

1) configure su tsconfig.jsonpara incluir sus tipos definidos ( src/typescarpeta, node_modules - depende de usted):

...other stuff...
"paths": {
  "*": ["node_modules/*", "src/types/*"]
}

2) cree un archivo src/types/global.d.tscon el siguiente contenido (¡ sin importaciones! - esto es importante), siéntase libre de cambiar anypara que coincida con sus necesidades + use la windowinterfaz en lugar de NodeJSsi está trabajando con el navegador:

/**
 * IMPORTANT - do not use imports in this file!
 * It will break global definition.
 */
declare namespace NodeJS {
    export interface Global {
        log: any;
    }
}

declare var log: any;

3) ahora finalmente puede usar / implementar logdonde sea necesario:

// in one file
global.log = someCoolLogger();
// in another file
log.info('hello world');
// or if its a variable
global.log = 'INFO'
Alexey
fuente
¿Cuál es la pathsde tsconfig.json? Los documentos no lo mencionan.
tambre
¿Y por qué se Globalescribe con mayúscula en las definiciones, pero no en el uso real?
tambre
@tambre no está seguro de qué documentos TS no lo tienen documentado, se pueden encontrar algunos detalles relacionados con esta configuración aquí: json.schemastore.org/tsconfig y aquí: basarat.gitbooks.io/typescript/docs/project/tsconfig.html Con respecto Globalcon capital: así es como se nombra la declaración de interfaz "global" en el espacio de nombres de nodejs.
Alexey
1

Necesitaba hacer lodash global para usar un archivo .js existente que no podía cambiar, solo requerir.

Descubrí que esto funcionó:

import * as lodash from 'lodash';

(global as any)._ = lodash;
TrueWill
fuente
0

Como complemento a la respuesta de Dima V, esto es lo que hice para que esto funcionara para mí.

// First declare the window global outside the class

declare let window: any;

// Inside the required class method

let globVarName = window.globVarName;

Jonathan Cardoz
fuente
¿Puede la persona que votó en contra de esto explicar el motivo?
Jonathan Cardoz
7
Bueno, esta es una solución como poner un trozo de cinta negra sobre la luz de "revisar el motor" en el tablero. Soluciona el problema pero no de la forma correcta. Elimina los tipos. No es una solución óptima; es una solución que también funciona en torno al propósito principal del mecanografiado: tener tipos.
Matthias
0

Esto funciona para mí, como se describe en este hilo :

declare let something: string;
something = 'foo';
Nacho Coloma
fuente