Typescript: Permitir que las definiciones de módulo se declaren como variables globales

Creado en 15 may. 2015  ·  11Comentarios  ·  Fuente: microsoft/TypeScript

Tengo el archivo de definición de tipo React (que se declara usando un módulo externo). En mis archivos de origen, generalmente hago:

import * as R from "react"

y luego puede usar felizmente R.createElement(... etc de una manera fuertemente tipada. Incluso puedo hacer:

let _r = R;
_r.createElement(...

Lo que quiero es no tener que importar R en cada archivo y, en cambio, tenerlo como una declaración global (sí, estoy dispuesto a contaminar el espacio de nombres global con algunas variables). Lo intenté, en un .d.ts :

import * as React from "react";
declare var R : React;

Sin embargo, esto no funciona, aparece "No se puede encontrar el nombre 'Reaccionar'". ¿Hay otra forma de exportar todo el módulo como global, sin tener que modificar el subyacente react.d.ts?

Question

Comentario más útil

Hola @Evertt, de hecho, ahora también recibo este error. Inicialmente, mi código fuente no usaba la sintaxis del módulo ES6, pero una vez que refactoricé algunos archivos a esa sintaxis, obtuve el mismo error. Investigué un poco y lo que funcionó para mí ahora es cuando creo el segundo archivo globals.d.ts y lo coloco también en la carpeta de mecanografía:

import * as _R from 'ramda';
import * as _mobx from 'mobx';

declare global {
  const R: typeof _R;
  const mobx: typeof _mobx;
}

De hecho, este archivo por sí solo parece "satisfacer" al compilador mecanografiado, por lo que en teoría no necesitaría los otros archivos que mencioné anteriormente. Sin embargo, en mi caso particular (estoy usando WebStorm) cuando solo tengo el archivo globals.d.ts, mi IDE me hacía ping constantemente para importar los módulos y también las finalizaciones en esos globales estaban incompletas. Así que básicamente guardé ahora ambos archivos en el directorio de mecanografía que satisface mecanografiado y mi IDE. No es realmente agradable, pero para los pocos globales que uno usa normalmente, creo que está bien mantener esos archivos.

Este es mi tsconfig.json para referencia:

{
  "compilerOptions": {
    "target": "ES5",
    "module": "amd",
    "moduleResolution": "node",
    "experimentalDecorators": true,
    "lib": [
      "ES6",
      "DOM",
      "ScriptHost"
    ],
    "sourceMap": true,
    "strictNullChecks": true
  },
  "include": [
    "types/**/*",
    "src/**/*"
  ]
}

No estoy usando webpack ni nada para empaquetar. Simplemente transpilo los archivos individuales y los cargo a través del sistema de módulo https://github.com/SAP/openui5 (que es similar a AMD) y los agrupo solo para producción.

La versión de TypeScript es: 2.2.1

Espero que ayude.

Todos 11 comentarios

No es posible hacer esto porque en el momento en que agrega una declaración import a un archivo fuente, se considera un módulo externo. ¿Alguna razón por la que no estás usando el archivo de definición de React que usa un global?

https://github.com/borisyankov/DefinitelyTyped/blob/master/react/react-global.d.ts

Me parece que esto resolvería el problema.

De hecho, también probé react-global.d.ts , lo que obviamente pone React en el espacio global, pero ¿cómo cambiaría el nombre globalmente y se lo haría saber a Typescript?

declare var _r = React;  // error Cannot find name 'React';

Mi caso de uso real sería poder elevar un módulo de utilidad / tipo común al espacio global para no tener que usar un montón de importaciones de rutas relativas para llegar a él. Puedo hacer esto en Javascript, pero estoy luchando sobre cómo le hago saber al compilador de TypeScript que lo hice.

@ahejlsberg - Estoy seguro de que tienes muchas más cosas importantes que hacer que aguantar mis reflexiones sobre casos extremos ... :)

Por ejemplo, podría crear un archivo de declaración r.d.ts :

/// <reference path="react-global.d.ts"/>
declare var R: typeof React;

y luego solo haga referencia a ese archivo en todas partes. O mejor:

/// <reference path="react-global.d.ts"/>
import R = React;

lo que le permitirá también hacer referencia a tipos de React como R.xxx.

Nunca antes había visto un uso de typeof , bastante bueno. Esto funciona muy bien para módulos ya definidos desde .d.ts , pero todavía no veo una forma de elevar un módulo externo definido en Typecript al espacio global y hacer que Typecript lo sepa. Tal vez porque es un anti-patrón y debería superarlo ...

Hemos tenido algunas solicitudes (por ejemplo, # 2357) para extender typeof para admitir módulos externos, pero hasta ahora no ha habido mucha demanda para la función.

En general, los programas se escriben sin módulos externos o exclusivamente con módulos externos. Aparte de la parte de arranque de una aplicación de navegador AMD, realmente no hay un entorno de ejecución en el que el modelo mixto sea posible. Entonces sí, es principalmente un anti-patrón.

¡Gracias por tomarse todo el tiempo para complacerme en esto! Acabo de comenzar a explorar módulos externos (para jugar con los próximos frameworks Angular2 y Aurelia). Temas como # 17, # 2338 y # 2839 parecen ser más de lo que estoy buscando al final. Con suerte, obtendré comentarios más claros a medida que profundice en mi proyecto actual.

¿Todavía no es posible hacerlo? Estoy intentando usar TypeScript con VueJS y agradecería mucho si pudiera importar algunas cosas al espacio de nombres global para que todos los componentes puedan usarlo sin tener que importar esas cosas. ¿Ha habido algún progreso o trucos para que esto funcione?

@Evertt

Encontré una forma que aparentemente funciona con mecanografiado 2.xx En mi caso, quiero exponer la biblioteca ramda como global R .

  1. npm install ramda @types/ramda
  2. crear archivo typings/ramda.d.ts
  3. agregue la carpeta typings recién creada a las inclusiones en .tsconfig.json:
"include": [
    "typings/**/*",
     ...
]
  1. agrega la magia a typings/ramda.d.ts :
import * as _R from 'ramda';

export as namespace R;
export = _R; 

Ahora todos los archivos ts en mi proyecto asumen que hay un R global escrito sin que yo haga más importaciones o lo que sea en esos archivos.

@geekflyer cuando trato de hacer eso usando el siguiente código en mi types/vue.d.ts :

import * as V from 'vue'

export as namespace Vue
export = V

Recibo el siguiente error cada vez que intento usar ese Vue global en algún lugar:

error TS2686: 'Vue' refers to a UMD global, but the current file is a module. Consider adding an import instead.

¿Recibiste ese error también en algún momento? Si es así, ¿qué hiciste al respecto?

editar

Si no recibe ese error y no está seguro de por qué recibo ese error, ¿estaría dispuesto a mostrarme su tsconfig.json completo y tal vez incluso la configuración de su paquete web?

Hola @Evertt, de hecho, ahora también recibo este error. Inicialmente, mi código fuente no usaba la sintaxis del módulo ES6, pero una vez que refactoricé algunos archivos a esa sintaxis, obtuve el mismo error. Investigué un poco y lo que funcionó para mí ahora es cuando creo el segundo archivo globals.d.ts y lo coloco también en la carpeta de mecanografía:

import * as _R from 'ramda';
import * as _mobx from 'mobx';

declare global {
  const R: typeof _R;
  const mobx: typeof _mobx;
}

De hecho, este archivo por sí solo parece "satisfacer" al compilador mecanografiado, por lo que en teoría no necesitaría los otros archivos que mencioné anteriormente. Sin embargo, en mi caso particular (estoy usando WebStorm) cuando solo tengo el archivo globals.d.ts, mi IDE me hacía ping constantemente para importar los módulos y también las finalizaciones en esos globales estaban incompletas. Así que básicamente guardé ahora ambos archivos en el directorio de mecanografía que satisface mecanografiado y mi IDE. No es realmente agradable, pero para los pocos globales que uno usa normalmente, creo que está bien mantener esos archivos.

Este es mi tsconfig.json para referencia:

{
  "compilerOptions": {
    "target": "ES5",
    "module": "amd",
    "moduleResolution": "node",
    "experimentalDecorators": true,
    "lib": [
      "ES6",
      "DOM",
      "ScriptHost"
    ],
    "sourceMap": true,
    "strictNullChecks": true
  },
  "include": [
    "types/**/*",
    "src/**/*"
  ]
}

No estoy usando webpack ni nada para empaquetar. Simplemente transpilo los archivos individuales y los cargo a través del sistema de módulo https://github.com/SAP/openui5 (que es similar a AMD) y los agrupo solo para producción.

La versión de TypeScript es: 2.2.1

Espero que ayude.

@geekflyer gracias que fue muy útil

¿Fue útil esta página
0 / 5 - 0 calificaciones