Typescript: Considere permitir el acceso a globales UMD desde módulos

Creado en 5 ago. 2016  ·  73Comentarios  ·  Fuente: microsoft/TypeScript

La retroalimentación del # 7125 es que algunas personas en realidad mezclan y combinan bibliotecas UMD globales e importadas, lo que no consideramos un escenario probable al implementar la función.

Tres opciones plausibles:

  1. Hagamos lo que hacemos hoy: mal porque no hay una buena solución
  2. Permita que alguna sintaxis o configuración diga "este UMD global está disponible globalmente" - algo complejo, pero factible
  3. Permitir el acceso a todos los globales de UMD independientemente del contexto: se pierden errores en los que las personas olvidan importar el global de UMD en un archivo. Estos son probablemente algo raros, pero sería tonto perderlos.

Parece que funcionaría, pero probablemente no lo haría:

  1. Marque los módulos UMD importados como "no disponibles para global" - incorrecto porque los módulos UMD se importarán en archivos de declaración durante el aumento de módulos. Sería extraño tener un comportamiento diferente de las importaciones de los archivos de implementación frente a los archivos de declaración.

Me inclino por la opción 3 por simplicidad, pero podría ver la opción 2 si hay alguna sintaxis o configuración razonablemente buena que podamos usar en un lugar lógico. Detectar el uso de un UMD global en una regla TSLint sería sencillo si alguien quisiera hacer esto.

Un camino a seguir sería implementar la opción 3 y si resulta que la gente comete el error "olvidó importar" con frecuencia, agregue una opción tsconfig globals: [] que especifique explícitamente qué globales UMD están permitidos.

Add a Flag Committed Suggestion good first issue help wanted

Comentario más útil

+1 en esto. Solo estaba tratando de usar React con SystemJS, y como React no se incluye muy bien, solo lo estoy cargando directamente desde el CDN en una etiqueta de script y, por lo tanto, los objetos React / ReactDOM están disponibles globalmente.

Estoy escribiendo código como módulos como la mejor práctica, pero esto se incluirá (Rollup) en un script de tiempo de ejecución que se ejecuta al cargar. Es una molestia (y una mentira) tener que import from react / react-dom, y luego configurar el cargador para que diga "no realmente, estos son globales" (similar a la configuración de WebPack de ejemplo dada en https: / /www.typescriptlang.org/docs/handbook/react-&-webpack.html). Sería mucho más fácil (y más preciso) simplemente tenerlos disponibles como globales en mis módulos. Los pasos que intenté, ya que parecían intuitivos, fueron:

  1. npm install --save-dev @types/react @types/react-dom
  2. En mi tsconfig.json: "jsx": "react", "types": ["react", "react-dom"]
  3. En mi módulo: export function MyComponent() { return <div>{"Hello, world"}</div>; }
  4. Del mismo modo: ReactDOM.render(...)

Sin embargo, esto da como resultado el error React refers to a UMD global, but the current file is a module. Consider adding an import instead .

Si esto funcionara, sería mucho más simple que fingir en el código que es un módulo y luego configurar el cargador / agrupador para que no lo sea. (O alternativamente, logré que hiciera lo que esperaba agregando un archivo que contiene lo siguiente. Ahora mis módulos pueden usar React & ReactDOM como globales sin error, pero es un poco feo / hacky, aunque puede haber una forma más sencilla de ' me he perdido):

import * as ReactObj from "react";
import * as ReactDOMObj from "react-dom";

declare global {
    var React: typeof ReactObj;
    var ReactDOM: typeof ReactDOMObj;
}

Todos 73 comentarios

En lugar de permitir el acceso a todos los globales de UMD independientemente del contexto, ¿no sería más sencillo permitir solo el acceso al global de UMD si el módulo UMD ha sido "referenciado" explícitamente (no importado) a través de la sintaxis ///<reference types=<>> , o mediante la configuración types en tsconfig.json?

En otras palabras, ¿por qué no permitir que se use ///<reference types=<>> dentro de un módulo?

Si dijimos que /// <reference type="x" /> significaba que x estaba disponible globalmente _en todas partes_, con frecuencia ocurrirá que algún archivo .d.ts en algún lugar hará referencia incorrecta a cosas que no son realmente globales ( Puedo decirte esto porque he estado manteniendo la rama 2.0 de DefinitelyTyped y es un error extremadamente común).

Por el contrario, si solo está disponible en ese archivo, entonces tendrá que copiar y pegar directivas de referencia por todas partes, lo que es realmente molesto. Estas directivas suelen ser idempotentes, por lo que introducir un comportamiento específico de archivo es extraño.

Veo. Bueno, si esto no afecta a nadie más, quizás sea mejor mantener el comportamiento actual. Solo tendré que hacer una transición completa hacia la importación de cosas como módulos.

Editar: me alegro de ver que esto afecta a muchas personas además de mí.

La teoría actual es simplemente pedirle a la gente que migre para usar módulos o no. Si otras personas se encuentran con esto, deje un comentario con exactamente qué bibliotecas estaba utilizando para que podamos investigar más.

Estoy usando lodash, que no viene con tipificaciones propias. También tengo una situación en la que en mi entorno de ejecución es más fácil usar declaraciones de importación de ruta relativa. Entonces, tengo una combinación de declaraciones de importación con rutas relativas locales y parientes de carpetas ('./foo' así como 'N / bar').

Si copio manualmente @types/lodash/index.d.ts en node_modules/lodash/ puedo hacer que las cosas se verifiquen.

Hasta ahora, mi solución era usar ///<amd-dependency path='../lodash' name="_"> (y ninguna declaración import ). Con este combo, las definiciones de @ types / lodash serían vistas 'globalmente' por el compilador y aún tendrían la ruta relativa correcta ( ../lodash ) en el JS emitido.

Espero que este sea un escenario lo suficientemente cercano a este problema.

Puedes aclarar

También tengo una situación en la que en mi entorno de ejecución es más fácil usar declaraciones de importación de ruta relativa.

y

Si copio manualmente @types/lodash/index.d.ts en node_modules/lodash/ puedo hacer que las cosas se verifiquen.

¿Por favor? No estoy familiarizado con este escenario, entonces, ¿cuál es el propósito de esto y por qué es útil?

Hola chicos,

Estoy en el proceso de buscar una solución a los actuales @types/bluebird declaración problema (por favor no pasar tiempo de leerlo). Descubrí que el problema podría resolverse agregando export as namespace Promise; al .d.ts, pero luego me encuentro con el problema descrito por este problema de github.

En resumen, me gustaría que funcionara lo siguiente:

  1. git clone -b vanilla-es5-umd-restriction-problem https://github.com/d-ph/typescript-bluebird-as-global-promise.git
  2. cd typescript-bluebird-as-global-promise
  3. npm install
  4. Edite node_modules/@types/bluebird/index.d.ts agregando export as namespace Promise; arriba de la línea export = Bluebird; .
  5. npm run tsc

Resultado actual:
Un par de errores de 'Promise' refers to a UMD global, but the current file is a module. Consider adding an import instead. .

Resultado Esperado:
La compilación tiene éxito.

Este problema es particularmente difícil, porque se desencadena por el uso de Promise tanto en el código del desarrollador como en el código de terceros (RxJS en ese caso). Este último asume que Promise es global (proporcionado por el estándar JS), por lo tanto, nunca cambiará a usar, por ejemplo, import Promise from std; // (not that "std" is a thing) .

Realmente agradecería una forma de usar módulos UMD como módulos importables y globales.

Gracias.

----------------------------- Actualización

Terminé resolviendo este problema de manera diferente (a saber: mediante el aumento de interfaces Promise y PromiseConstructor ).

La opción "globals": [] tsconfig parece preferible a hacerlas visibles en todas partes. Con la declaración de UMD convirtiéndose en la norma, las probabilidades de olvidar accidentalmente importar un módulo son altas. Considere mantener el comportamiento actual. Esto debería ser un error.

Como anécdota, recuerdo cuando moment eliminó su variable global window.moment en un lanzamiento puntual. Pensamos que lo habíamos estado importando juiciosamente en todas partes, pero nos habíamos olvidado de 5 lugares.

Por supuesto, un paquete UMD estará disponible en el ámbito global en tiempo de ejecución, pero cuando esté disponible dependerá del orden en que se carguen otros módulos.

+1 en esto. Solo estaba tratando de usar React con SystemJS, y como React no se incluye muy bien, solo lo estoy cargando directamente desde el CDN en una etiqueta de script y, por lo tanto, los objetos React / ReactDOM están disponibles globalmente.

Estoy escribiendo código como módulos como la mejor práctica, pero esto se incluirá (Rollup) en un script de tiempo de ejecución que se ejecuta al cargar. Es una molestia (y una mentira) tener que import from react / react-dom, y luego configurar el cargador para que diga "no realmente, estos son globales" (similar a la configuración de WebPack de ejemplo dada en https: / /www.typescriptlang.org/docs/handbook/react-&-webpack.html). Sería mucho más fácil (y más preciso) simplemente tenerlos disponibles como globales en mis módulos. Los pasos que intenté, ya que parecían intuitivos, fueron:

  1. npm install --save-dev @types/react @types/react-dom
  2. En mi tsconfig.json: "jsx": "react", "types": ["react", "react-dom"]
  3. En mi módulo: export function MyComponent() { return <div>{"Hello, world"}</div>; }
  4. Del mismo modo: ReactDOM.render(...)

Sin embargo, esto da como resultado el error React refers to a UMD global, but the current file is a module. Consider adding an import instead .

Si esto funcionara, sería mucho más simple que fingir en el código que es un módulo y luego configurar el cargador / agrupador para que no lo sea. (O alternativamente, logré que hiciera lo que esperaba agregando un archivo que contiene lo siguiente. Ahora mis módulos pueden usar React & ReactDOM como globales sin error, pero es un poco feo / hacky, aunque puede haber una forma más sencilla de ' me he perdido):

import * as ReactObj from "react";
import * as ReactDOMObj from "react-dom";

declare global {
    var React: typeof ReactObj;
    var ReactDOM: typeof ReactDOMObj;
}

También estoy de acuerdo con las opciones tres más globales: [] respaldo. Eso parece bastante intuitivo para los usuarios nuevos y antiguos y daría la funcionalidad exacta que la gente necesita.

No soy un especialista en el código, por lo que realmente no puedo decir si 2 sería más preferible o no, pero creo que también sería intuitivo, dada la configuración sencilla.

Si quisiera buscar ayuda para implementar alguno de estos, ¿dónde debería ir?

Esto realmente debería estar detrás de una bandera. Es un peligro de refactorización masivo. Incluso si la bandera se especifica como verdadera de forma predeterminada. Creo que esto tiene que seguir funcionando en el escenario original, de lo contrario, perderemos el beneficio principal de las declaraciones UMD.

React no se combina muy bien

@billti, ¿puedes explicarme?

Es una molestia (y una mentira) tener que import from react / react-dom, y luego configurar el cargador para que diga "no realmente, estos son globales"

La única razón por la que escribí eso en el tutorial es porque usar externals reduce el tiempo de empaquetado. Si usa la variable global React sin importar, no podrá cambiar fácilmente a los módulos más adelante, mientras que las importaciones le brindan la flexibilidad de usar cualquiera de ellos dado su cargador.

Consulte este número (https://github.com/rollup/rollup/issues/855) para ver un ejemplo sobre cómo están tratando de optimizar la agrupación y los tamaños observados. Efectivamente, en mi configuración (usando Rollup) vi ganancias de tamaño mínimas al empaquetar React, por lo que prefiero servirlo desde un CDN. Para mí, eso tiene los beneficios de:

a) Menos solicitudes (y ancho de banda) a mi sitio.
b) Menos tiempo para agrupar en mi cadena de construcción.
c) Menos código para volver a descargar en el cliente cada vez que presiono un cambio (ya que solo mi código está en el paquete que se vuelve a descargar y React todavía está en la memoria caché del cliente sin modificar, obteniendo así 304s).

Mirando en las herramientas de desarrollo de Chrome al cargar el sitio, React y React-dom (las versiones minificadas), en una conexión HTTP con GZip, son solo 47kb de tráfico de red, que es menos que la mayoría de las imágenes en un sitio, así que no estoy preocupado por tratar de reducir tanto de todos modos, a menos que se puedan obtener grandes ganancias (por ejemplo, una reducción del 50%).

Como apéndice: también me gustaría señalar que sin esta opción, también está obligando a la gente a utilizar un paquete que elude estas importaciones, ya que el compilador de TypeScript en sí no tiene una configuración para decir "este módulo es realmente un global", y por lo tanto emitir importaciones (o requiere, o define) para módulos que no se resolverían en tiempo de ejecución.

@billti SystemJS tiene soporte completo para este escenario. Puede cambiar entre usar un paquete instalado localmente durante el desarrollo y usar una CDN en producción. También tiene soporte completo para metadatos que especifica que todas las importaciones deben indicar referencias a una variable global que se buscará una vez y se adjuntará al objeto de ventana cuando se necesite por primera vez; en producción, esto puede provenir de un CDN. No he hecho esto con react pero lo he hecho con angular 1.x

Gracias @aluanhaddad . Interesante ... en realidad estaba tratando de hacer que algo similar funcionara que me llevó a este obstáculo, y no pude resolverlo, así que esta mañana hice la pregunta sobre el repositorio de SystemJS. Si puede responder cómo lograr https://github.com/systemjs/systemjs/issues/1510, sería realmente útil :-)

Nota: Mi otro comentario sigue en pie, que la emisión de TypeScript en sí no se puede usar sin esto, ya que necesita algo como SystemJS / WebPack / Rollup, etc. para asignar las importaciones a globales para que se ejecute el código.

Echaré un vistazo y veré si puedo hacer un ejemplo de trabajo, no lo he hecho en bastante tiempo y no tengo acceso al código fuente que tenía en ese momento, pero estoy cien por ciento seguro. Es posible.

Para su segundo punto, eso es exactamente lo que hace SystemJS. Mapeará esas importaciones al global y comprenderá que el global realmente se está solicitando y ya se ha cargado. La salida es definitivamente utilizable

FYI: Conseguí que esto funcionara en SystemJS usando la API de SystemJS y agregué mi solución en https://github.com/systemjs/systemjs/issues/1510 . Gracias.

Con respecto a mi segundo punto: Sí, sé que eso es exactamente lo que pueden hacer los cargadores. Ese es mi punto, pueden asignar un módulo importado a un global, pero TypeScript no puede, por lo que debe usar un cargador para que su código sea válido en tiempo de ejecución. Entonces es un catch-22 con este problema original, donde no puede declarar que el global (en este caso React) está disponible en el módulo, debe importarlo como si fuera un módulo (que no lo es) .

Mi otro comentario sigue en pie, que la emisión de TypeScript en sí no se puede usar sin esto, ya que necesita algo como SystemJS / WebPack / Rollup, etc. para asignar las importaciones a globales para que se ejecute el código.

@billti No lo entiendo. ¿Cuál es un escenario en el que su única opción es usar la versión global de un módulo, pero TypeScript no le permite hacer eso? Sólo he visto escenarios donde una biblioteca está disponible como un global y un módulo.

@DanielRosenwasser Creo que quiere decir que React es en realidad un global en tiempo de ejecución como en un miembro del objeto global, debido a cómo se está cargando.

@billti Impresionante que lo hayas hecho funcionar.

Re tu segundo punto: veo lo que quieres decir.

Supongo que mi sensación es que, en un escenario de navegador, porque necesita usar un cargador como RequireJS o un empaquetador como Webpack porque ningún navegador admite módulos, pero no hace ninguna diferencia. (Escuché que Chakra lo tiene disponible detrás de una bandera). Por lo tanto, no hay forma de ejecutar el código sin una herramienta adicional. Es una especie de implicación de la salida que contiene define , require , o System.register que el código _JavaScript_ emitido probablemente no sea portátil. Sin embargo, veo la importancia de la distinción "módulo vs no módulo".

Puede utilizar esta solución alternativa para al menos referirse al "módulo" una sola vez.

_shims.d.ts_

import __React from 'react';

declare global {
  const React: typeof __React;
}

Entonces puede usarlo en cualquier otro lugar sin importarlo.
Además, esto es muy explícito, aunque un poco torpe, porque estás diciendo que React se ha vuelto global y esa es también la razón por la que ya no tienes que importarlo.

Mira tus shims.d.ts, si subes algunas publicaciones, verás que eso es lo que hice por ahora (las grandes mentes piensan igual) ;-)

Puedo hacer que funcione de varias maneras ahora, ese no es el punto. Estamos tratando de hacer que TypeScript sea fácil de adoptar y hacer que los usuarios caigan en el pozo del éxito, no en el pozo de la desesperación. Con eso en mente, a menudo me hago dos preguntas cuando trato de usar TypeScript y encuentro problemas: a) ¿Es este código válido? Yb) ¿Los clientes van a intentar hacer esto?

Dado que tenía la versión (no TypeScript) haciendo lo que quería en Babel en aproximadamente el tiempo que me tomó escribirlo, creo que es justo decir que el código es válido. Como la página de instalación de los documentos de React muestra cómo usar etiquetas de script de una CDN para incluir React, supongo que varias personas también lo intentarán. (FWIW: He pasado más tiempo del que me gustaría recordar trabajando con varios módulos y cargadores JS, por lo que no es que no los conozca, solo quería escribir mi código de esta manera).

Si TypeScript no va a admitir ciertos patrones válidos de escritura de código, deberíamos intentar hacer eso inmediatamente obvio y dirigir a la gente hacia la derecha (lo cual es un desafío en mensajes de error o documentos concisos). Pero personalmente, no creo que TypeScript no deba admitir patrones porque no creemos que sean "mejores prácticas" o "canónicas". Si el código es válido y algunos desarrolladores de JavaScript pueden querer escribirlo, TypeScript debería intentar admitirlo. Cuanto más solicitemos que cambien su código y reconfiguren su canal de compilación para que TypeScript funcione (como se recomienda aquí para migrar mi aplicación trivial), menos desarrolladores se moverán.

En cuanto a la solución ... simplemente escupir aquí, pero quizás la opción del compilador "lib", que ya define efectivamente qué API están disponibles en todo el proyecto, también podría tomar valores de formato @types/name para que las bibliotecas agreguen globalmente (e incluso admitir rutas relativas tal vez).

Estamos tratando de hacer que TypeScript sea fácil de adoptar y hacer que los usuarios caigan en el pozo del éxito, no en el pozo de la desesperación.

Creo que estamos tratando de llevar a los usuarios a la boca del éxito en este momento. Si un módulo solo define condicionalmente un global, entonces está guiando accidentalmente a los usuarios para que usen algo que no existe. Entonces veo algunas opciones diferentes:

  1. Cree una construcción export as namespace foo aumentada que solo sea visible si no la importa un módulo.
  2. No haga nada y siga presionando a la gente para que use la importación; en mi opinión, esto está más o menos bien, ya que de todos modos hemos hecho que el mensaje de error sea razonablemente prescriptivo.
  3. Permitir que las personas usen el UMD de todas partes; honestamente, no soy tan fanático de esta idea.

@billti

Mira tus shims.d.ts, si subes algunas publicaciones, verás que eso es lo que hice por ahora (las grandes mentes piensan igual) ;-)

Lo siento, me perdí eso, muy lindo;)

No creo que TypeScript no deba admitir patrones porque no creemos que sean "mejores prácticas" o "canónicas".

No creo que TypeScript esté siendo proscriptivo aquí, creo que está haciendo lo que dice, diciéndome que tengo un error. Muchas bibliotecas tienen demostraciones y tutoriales en los que se cargan a sí mismos como globales y luego proceden a usar la sintaxis del módulo ES. No creo que estén siendo los mejores ciudadanos al hacer esto, pero esa es otra discusión.

Dicho esto, si los módulos se utilizan principalmente como un azúcar sintáctico _percibido_ sobre los globales, entonces su falla está cerca porque no son un azúcar sintáctico en absoluto. En todo caso, son una sal sintáctica (¿quizás un impuesto?) Que consumimos para obtener beneficios como el verdadero aislamiento del código, la libertad de la ordenación de etiquetas de script, la declaración de dependencia explícita, el escape del infierno del espacio de nombres global y otros beneficios. La sintaxis de los módulos no es ergonómica, en el mejor de los casos es detallada, pero es la semántica de los módulos lo que hace que valga la pena.

Creo que si la gente usa TypeScript, al menos en archivos .ts , supongo que quieren obtener los beneficios de un análisis de código estático sólido. Babel no hace esto, asumiendo que React existe pero sin tener conocimiento de ello. Esto es cierto a pesar de que los módulos ES se han especificado deliberadamente para que sean susceptibles de análisis estático.

@DanielRosenwasser

Cree una exportación aumentada como construcción de espacio de nombres foo que solo sea visible si no la importa un módulo.

Suena como la mejor manera de resolver esto.

Aquí hay otro caso en el que esto causó problemas:

En un proyecto en el que estoy trabajando actualmente, mezclamos inclusiones locales (principalmente por razones históricas) con módulos npm. Al final, todo se une usando Rollup o Browserify, así que está bien.

Utilizo un archivo .js del proyecto emojione que simplemente copié en el código base. Más tarde agregué las declaraciones de tipo para DefinitelyTyped: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/13293 Pensé que ahora podría simplemente cargar los tipos y todo funcionaría. Pero ese no parece ser el caso, porque TypeScript no me deja acceder al global.

La razón por la que no me estoy moviendo al módulo npm es que el módulo npm también incluye varios megabytes de sprites y PNG. Solo necesito ese script de 200 KB. Con declaraciones de tipo.

Con AngularJS, la solución alternativa fue declare var angular: ng.IAngularStatic . Pero eso no funciona con los espacios de nombres, ¿verdad?

@dbrgn Está experimentando un problema diferente. Si el módulo es realmente global, entonces su definición de tipo es incorrecta. No declara una declaración global ni es una declaración de estilo UMD (se trata de declaraciones de estilo UMD), en realidad declara solo un módulo ES puro.

Si el módulo representa un global, no exporte en el nivel superior del archivo, eso lo convierte en un módulo.

Con AngularJS, la solución fue declarar var angular: ng.IAngularStatic. Pero eso no funciona con los espacios de nombres, ¿verdad?

Funciona con espacios de nombres.

El resultado de la discusión en nuestra reunión de diseño fue que estamos considerando permitir siempre el UMD y agregar una bandera que haga cumplir la restricción actual. La restricción también se extenderá para trabajar en el acceso a tipos desde un UMD global.

Habiendo pensado más en esto, sigo pensando que lo mejor es crear un nuevo tipo de declaración. Esta bandera es menos visible que la nueva sintaxis, que solo necesita ser escrita una vez por el autor del archivo de declaración.

Esto se necesita desesperadamente para el código y las herramientas existentes. Hasta que Javascript deje de reproducirse rápido y pierda con los sistemas de módulos, necesitamos flexibilidad para trabajar con el código tal como existe. Emita una advertencia, pero no falle la compilación. He perdido días tratando de hacer que el código heredado funcione bien con el resumen y el mecanografiado.

UGH.

Sé que hay mucha gente a la que le gusta reírse de Java, pero los módulos básicos de Java al menos funcionan. Los tarros funcionan

No tengo que ajustarme a 14 estándares de módulos ad hoc diferentes, o intentar compilar un módulo js a partir de archivos de origen en el formato que la herramienta de acumulación / agrupación del día realmente consumirá sin hacer caca, y también generará un formato de módulo eso funcionará bien con las declaraciones de importación / exportación de TypeScript y los archivos d.ts de terceros para que TSC realmente decida crear el código en lugar de quejarse de algo a lo que va "SOLO USE LA IMPORTACIÓN DE DARN, SERÁ UNA AT TIEMPO DE FUNCIONAMIENTO ".

El truco shims.d.ts funciona bien. Pero ugh.

Solución temporal para quienes usan Webpack https://github.com/Microsoft/TypeScript/issues/11108#issuecomment -285356313

Agregue externals a webpack.config.js con los globales UMD deseados.

    externals: {
        'angular': 'angular',
        'jquery': 'jquery'
        "react": "React",
        "react-dom": "ReactDOM"
    }

Creo que esto debería ser posible para facilitar la migración de bases de código existentes.

Tengo un proyecto implementado con requirejs donde jQuery se incluye como global, porque hay algunos complementos que amplían jQuery solo si se encuentra como global.

El código en algunos de los módulos depende de esos complementos, que no estarían disponibles si jQuery se importara como módulo. Para que esto funcione, tendría que modificar todos los complementos para que funcionen con jQuery cargado como módulo, cargándolos también como módulos (y adivinar dónde son necesarios).

Además, también hay páginas que usan javascript sin cargadores de módulos. Entonces, los complementos deberían funcionar tanto con globales como con módulos.

Aparte de jQuery, hay otros scripts con el mismo problema como knockout y otros. Esto hace que la migración del proyecto sea una tarea sencilla. O, desde un punto de vista realista, inviable.

Por supuesto, este no es el mejor patrón y no lo usaría en un nuevo proyecto. Pero no creo que sea el único con este problema

¿Tendría sentido usar types en tsconfig.json para esto? Por ejemplo, sin types establecido, obtiene el comportamiento implícito actual y con types establecido, literalmente está diciendo "estas cosas son globales" y puede forzar que el espacio de nombres UMD aparezca globalmente. De todos modos, ese es el comportamiento que existe hoy en día (menos la fuerza global). Esto se opone a la introducción de una nueva opción globals .

Creo que es una buena idea. En mi caso hay scripts que usan una biblioteca UMD como global y otros como módulo. Podría resolver este problema con dos tsconfig.json diferentes que abordan cada caso. Realmente sencillo.

@blakeembrey Aunque usar types tiene sentido, no estoy muy interesado en la idea de sobrecargarlo ya que ya tiene problemas. Por ejemplo, la construcción <reference types="package" /> ya tiene la limitación de que no admite "paths" . "package" debe hacer referencia a un nombre de carpeta en @types

Estoy teniendo dificultades para seguir esta conversación. ¿Ha habido actualizaciones o resoluciones planificadas para esto? Parece que esto es algo que podría ser útil en escenarios como cuando lodash es una parte tan integral de una aplicación, o cuando más bibliotecas de terceros se convierten a una estructura más modularizada en lugar de depender simplemente de estar en la ventana.

¿Existe una forma planificada de abordar esto o al menos de documentar cómo debe resolverse con la versión disponible actual?

Hola @mochawich Recibo el siguiente error al usar la definición de React como externos y no usar la sintaxis declare global :

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

@cantux TypeScript no lee la configuración de Webpack. Si ha hecho que React esté disponible globalmente, puede declare eso, pero ¿por qué no usar módulos?

@aluanhaddad principalmente porque estaba confundido con el trabajo realizado por llamada de importación. Toqué algunos, ¿son correctas las siguientes declaraciones?

Pagamos la pequeña tarifa de realizar una solicitud cuando importamos un módulo. Esto asegura que lo que estamos usando esté disponible en la memoria, si se solicitó previamente, el módulo se carga desde la caché, si el módulo no existe, se recupera. Si desea eludir esta solicitud, simplemente defina algo como global y TypeScript confía ciegamente en usted de que está disponible (y si usa un paquete inteligente, las declaraciones de importación pueden incluso reemplazarse / eliminarse).

Si son correctos, podríamos eliminar los comentarios por brevedad, el hilo es un gigante tal como está.

Como @codymullins preguntó anteriormente, ¿alguien puede resumir la solución actual para este problema? Acabo de actualizar la definición del tipo lodash y obtuve muchos errores TS2686.

Mi solución actual fue piratear el archivo typedef para que se ajustara al antiguo estándar de trabajo, pero eso no es viable si comienzan a romperse más archivos typedef.

Mi escenario es el siguiente:

  • en mis aplicaciones de una sola página, importo una serie de bibliotecas (incluido lodash) en un

el ejemplo de corrección mencionado anteriormente funciona, aunque vscode lo destaca como un error (¡aunque todavía lo completa correctamente!)

Por favor, no dé errores al acceder a los globales UMD en los módulos. El proyecto masivo en el que estoy trabajando está hecho en AngularJS y estamos usando Typecript para la aplicación, pero, por supuesto, necesitamos Typecript para conocer los tipos angular UMD globales y angulares de @types/angular . Pensarías que sería tan fácil como agregar "angular" a types en tsconfig.json , pero, por alguna razón, no lo es, y TSC me grita. Por mucho que desearía que todos los paquetes de NPM fueran mecanografiados puros, la mayoría de ellos son JS simples y lo serán durante mucho tiempo. Realmente no entiendo por qué TSC no puede simplemente callarse cuando importamos un d.ts diciendo que hay un UMD global. Esta situación es más que común: todos los proyectos de Typescript en los que he trabajado usa al menos una biblioteca JS que tengo que agrupar y hacer referencia usando definiciones de tipo.

¿Hay alguna actualización sobre esto?

Mi caso de uso: estoy trabajando en una gran base de código existente que hace un uso intensivo de CDN. Las utilidades comunes se importan a través de etiquetas de script en muchas páginas (por ejemplo, clipboardjs, lodash). Me gustaría hacer referencia a esas variables globales ya que están disponibles en la página. Sin usar módulos, es bastante fácil compilar mecanografiado, usando /// <reference type="$name" /> en la parte superior de los archivos fuente relevantes. Sin embargo, esto deja de funcionar al intentar crear módulos.

Parece que se han propuesto dos enfoques en el hilo:

  1. Haga que los tokens de importación /// <reference type="$name" /> en el espacio de nombres del archivo actual.

  2. Una opción del compilador / variable de configuración en tsconfig.json (ex. "globals" , "types" )

Creo que ambos enfoques son buenos. Si bien estoy de acuerdo con la crítica de la opción 1 de @RyanCavanaugh :

Por el contrario, si solo está disponible en ese archivo, entonces tendrá que copiar y pegar directivas de referencia por todas partes, lo cual es realmente molesto.

Creo que es mucho más molesto que no se puedan usar módulos junto con los globales UMD debido al comportamiento actual. Alguna solución es mejor que ninguna.

¿Sigue pendiente este problema? Y si es así, ¿cuál es la solución actual?

Si instala el paquete @types , los paquetes que no se importan como módulos estarán disponibles como globales.

Por ejemplo, si yo npm install -D @types/underscore en la raíz de mi proyecto, entonces puedo escribir módulos que no importen nada del guión bajo, pero el _ global está disponible (ver más abajo).

types-ref

¿Es eso lo que buscas?

@billti Tal vez lo esté entendiendo mal, pero tu ejemplo no me funciona.

Mínimo necesario para reproducir:

js / foo.ts:

// <reference types="js-cookie">

import { Bar } from "./bar";

const Foo = {
    set: function() {
        Cookies.set("foo", "bar");
    },
    get: function() {
        console.log(Cookies.get("foo"));
    }
};

window.onload = function() {
    console.log(Cookies);
}

js / bar.ts

const Bar = {
    x: 3
};

export { Bar };

package.json:

{
  "name": "foo",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "private": true,
  "devDependencies": {
    "@types/js-cookie": "^2.1.0",
    "typescript": "^2.7.1"
  },
  "dependencies": {
    "http-server": "^0.11.1"
  }
}

tsconfig.json

{
    "compilerOptions": {
        "module": "system"
    },
    "files": [
        "js/foo.ts"
    ]
}

Error de mensajes:

js / foo.ts (7,3): error TS2686: 'Cookies' se refiere a un UMD global, pero el archivo actual es un módulo. En su lugar, considere agregar una importación.
js / foo.ts (10,15): error TS2686: 'Cookies' se refiere a un UMD global, pero el archivo actual es un módulo. Considere agregar una importación en su lugar.
js / foo.ts (15,14): error TS2686: 'Cookies' se refiere a un UMD global, pero el archivo actual es un módulo. Considere agregar una importación en su lugar.

El comportamiento que obtiene depende de si el módulo importado se escribió como un módulo UMD "adecuado" (este es el comportamiento con "Cookies") o un módulo "funciona en ambos sentidos al mismo tiempo" (que es cómo se escribe lodash) .

La inconsistencia de las personas que escriben correctamente un archivo .d.ts que describe cómo funciona el objeto en tiempo de ejecución, y la opacidad de la experiencia para los desarrolladores, es la razón por la que me estoy inclinando mucho en la dirección de "eliminar la restricción global UMD". Podríamos ponerlo en --strict con una opción de exclusión de --noStrictUMD .

La otra cosa con la que me encontré fue lidiar con el cargador AMD personalizado de Mónaco. Admiten algún subconjunto del comportamiento de AMD (inserte un enorme eyeroll) pero pisotean el 'require' global, por lo que es realmente difícil usar módulos UMD adecuados con él, ya que esos módulos tienden a ver el 'require' global y luego no se cargan correctamente en Cargador de módulos Monaco. Terminas colocando las bibliotecas UMD JS encima de la etiqueta de script para el cargador de Monaco y luego TS se queja porque estás accediendo a las globales desde un módulo (que debes ser para importar las API de Monaco).

@RyanCavanaugh

La otra cosa con la que me encontré fue lidiar con el cargador AMD personalizado de Mónaco. Admiten algún subconjunto del comportamiento de AMD (inserte un enorme eyeroll) pero pisotean el 'require' global, por lo que es realmente difícil usar módulos UMD adecuados con él, ya que esos módulos tienden a ver el 'require' global y luego no se cargan correctamente en el Cargador de módulos Monaco.

😁

¿Alguna posibilidad de que arreglen eso?

Últimamente he estado pensando mucho en el costo de complejidad de los módulos. Tantos cargadores, agrupadores, transpiladores, administradores de paquetes y marcos interdependientes y parcialmente compatibles representan una cantidad realmente no trivial de complejidad de acreditación. (Estoy seguro de que no necesitas ningún recordatorio 🙉).

Como desarrolladores, hemos aceptado cadenas de herramientas que son órdenes de magnitud más complejas que hace 5-6 años, y la principal fuente de complejidad han sido los módulos.

Si nos damos por vencidos y comenzamos a cargar estos paquetes UMD como globales, ¿para qué ha sido todo?

Y sin embargo ... la gente está haciendo eso. ¡Este es terrible!

Quiero decir, esta respuesta de desbordamiento de pila tiene 61 👍 y ha estado sugiriendo todas las cosas incorrectas para el 99% de los paquetes durante el último medio año. (el autor lo actualizó amablemente para mencionar los módulos como una _opción_ para las dependencias de UMD debido a algunos comentarios proporcionados esta mañana)

¡Esto no puede permitir que todo esto haya estado en vena y vuelva a los globales!

Y sin embargo ... la gente está haciendo eso. ¡Este es terrible!

El problema es que los módulos JS están terriblemente mal concebidos e implementados, por lo que es mucho mejor y más fácil volver a usar globales. Si los módulos se hubieran diseñado e implementado correctamente desde el principio ...

Mezclamos y combinamos módulos y globales de UMD porque es demasiado complicado cargar nuestras dependencias como módulos con diferentes niveles de compatibilidad con varios cargadores y algunos cargadores que no admiten la agrupación de dependencias directas y, en su lugar, debe utilizar nuestro preprocesador especial que toma un minuto para correr.

Esta "característica" simplemente significa que no usamos el soporte oficial del módulo UMD aunque sí usamos módulos UMD. Simplemente exportamos como global desde el archivo .d.ts y luego manualmente tenemos nuestro propio módulo con ese nombre que reexporta todo.

¿Algún avance en esto? Realmente me gustaría que la opción 2 funcionara:

Permita que alguna sintaxis o configuración diga "este UMD global está disponible globalmente"

Además, no ayuda que haya tantas bibliotecas js al estilo de la vieja escuela
allí, y reescribirlos todos está fuera de discusión. Solo trabajando en un sólido
config para que Rollup los maneje todos correctamente, desperdicia horas de mi tiempo.

La gente se ríe de "Enterprise Java", pero Java simple viene con una funcionalidad
sistema de módulos en 1.0. No fue perfecto, pero no fue un completo desastre.

Como es "Permitir globales de estilo UMD" definitivamente debería ser una opción.

El lunes 2 de abril de 2018 a las 1:40 a. M. Kagami Sascha Rosylight <
[email protected]> escribió:

Tuve que solucionarlo con:

/ * módulo: es2015 * /
// js-yaml admite UMD pero no el módulo ES2015! import * as _jsyaml from "js-yaml"; declare var jsyaml: typeof _jsyaml; jsyaml.safeLoad ("");

-
Estás recibiendo esto porque comentaste.
Responda a este correo electrónico directamente, véalo en GitHub
https://github.com/Microsoft/TypeScript/issues/10178#issuecomment-377885832 ,
o silenciar el hilo
https://github.com/notifications/unsubscribe-auth/AA50ljAD33sr09EGFVAsURbu1x75X-lOks5tkeQCgaJpZM4Jd8jX
.

>

Daniel Joyce

Los mansos heredarán la tierra, porque los valientes estarán entre las estrellas.

Estoy usando three.js en un proyecto Angular. Lo importo como

import * as THREE from "three";

import {Vector3} from "three"; también funciona como se esperaba.

Con los paquetes three y @types/three npm instalados, todo funciona bien. Bajo el capó, supongo que esto está usando three/build/three.module.js . El archivo @types/three/index.d.ts usa la notación export as namespace THREE , con la que no estoy del todo cómodo, pero bueno, funciona.

En este caso particular, el problema es que hay otro archivo relacionado en el sistema three.js llamado OrbitControls.js (que te permite rotar imágenes en 3D con tu dedo o ratón, básicamente). El problema es que aunque esta función es semioficialmente parte de la distribución three.js, es un archivo JS simple y simple que se encuentra en el árbol examples y se coloca directamente en la propiedad THREE de la ventana y utiliza directamente otras API que espera encontrar presentes en window.THREE . Entonces, incluso si "requiero" el archivo con

require("three/examples/js/controls/OrbitControls.js");

no puede encontrar window.THREE para colocarse ni acceder a otras partes del sistema TRES que utiliza. Puedo incluir toda la biblioteca directamente usando la propiedad Angular scripts en angular.json (aproximadamente equivalente a una etiqueta <script> pasada de moda), pero luego, si no me equivoco, habrá cargado la biblioteca dos veces.

Para evitar eso, eliminé la declaración import * as THREE from "three"; , y bueno, todavía puede resolver tipos como foo: THREE.Vector3 , pero se atraganta con referencias como new THREE.Vector3() con el infame

'TRES' se refiere a un UMD global, pero el archivo actual es un módulo. Considere agregar una importación en su lugar. [2686]

En este punto, estoy pensando que solo tendré que tomar el archivo OrbitControls.js y ES6-ify y / o TS-ify it, que es lo que parece que más de una persona ya ha hecho en la forma de cosas como `orbit-controls-es6 , así que tal vez debería simplificar mi vida y usar eso, aunque detesto poner mi vida en manos de otras personas de esa manera.

En una nota semi-no relacionada, una rareza es que @types/three define tipos para OrbitControls , incluso si el código en sí no está en el módulo three . Sin embargo, no puedo averiguar cómo asociar todos esos tipos que definen una clase llamada OrbitControls con cualquier cosa; me gustaría declarar que la exportación predeterminada del orbit-controls-es6 es de este tipo, pero cómo hacerlo se me escapa.

La solución que finalmente se me ocurrió, de la que estoy profundamente avergonzado, es:

import * as THREE from "three";
Object.defineProperty(window, "THREE", {get() { return THREE; }});
require("three/examples/js/controls/OrbitControls.js");

Funciona, aunque estoy un poco confundido por qué. El archivo requerido tiene una línea como

THREE.OrbitControls = funtion() { };

que parece que terminaría asignándose a los TRES "espacios de nombres" que resultan de la instrucción import * as THREE from "three"; , que no debería funcionar, ¿verdad?

@RyanCavanaugh me pidió que copiara mis comentarios de # 26223 aquí:

Mantengo una base de código TypeScript bastante grande (monorepo interno de Google) que tiene varias bibliotecas definitivamente tipadas de las que la gente depende. Originalmente, los usuarios solo confiaban en tipos globales para bibliotecas como angular , antes de que .d.ts se convirtieran en módulos externos. Luego migramos la base del código para usar módulos e importaciones explícitas. De hecho, esperábamos que export as namespace d globales UMD siempre requirieran una importación explícita para usar símbolos, tanto para referencias de tipo como de valor, y ni siquiera nos dimos cuenta cuando migramos (¡uy!).

Permitir el uso de código no importado es generalmente problemático para nosotros:

  • significa que el código se basa en definiciones de tipo "de fondo" globales, lo que hace que el código sea más difícil de leer (en particular, en navegadores de repositorios o revisión de código sin ir al símbolo).

  • oscurece las dependencias del código

  • evita las restricciones de "debe tener una dependencia explícita del nivel de compilación en todas las importaciones" que implementamos en bazel, también conocido como "departamentos estrictos".

    En una base de código grande, su código debe tener dependencias explícitas; de lo contrario, el repositorio se vuelve inmanejable. Ahora, si tiene un encadenamiento de dependencia A -> B -> C y tipos globales, es fácil hacer que el código A compile solo porque B tiene una dependencia en C . Si B luego elimina su dependencia, rompe A , lo que significa que los cambios tienen un efecto dominó inesperado en el repositorio, violando el aislamiento del código.

  • hace que el código importe de manera inconsistente el módulo con un prefijo para los valores y use sus tipos con otro prefijo (en particular para AngularJS, ng vs angular)

Podemos solucionar esto eliminando esas declaraciones export as namespace en nuestra copia del proveedor de DefinitelyTyped, pero al menos para nosotros, esta característica va en contra de la capacidad de mantenimiento del código y nuestros objetivos de ingeniería. Creo que los problemas son más pronunciados en una situación de monorepo como Google, pero generalmente también se aplican en bases de código más pequeñas.

Los puntos que ha publicado son absolutamente irrelevantes para nuestra situación. Nos vemos obligados a implementar nuestro propio código con módulos AMD y suministrar nuestras dependencias con módulos UMD debido a circunstancias que están en general fuera de nuestro control (pero resumiría que los módulos JS tienen terribles defectos tanto en el concepto como en la implementación). Esta característica nos permitiría simplificar nuestra vida considerablemente.

Posiblemente con TS3 podríamos descubrir cómo evitar esto, pero incluso si lo hiciéramos, probablemente pasarían al menos dos años antes de que terminemos todos los cambios necesarios, por lo que esta aún sería una característica muy útil para nosotros.

Pregunta abierta: ¿Sería suficiente una bandera global para "Permitir el acceso a todos los módulos UMD", o la gente realmente necesita un control por módulo sobre el error?

Vote ❤️ por "solo una bandera"
Vote 🎉 por "necesita control por módulo"

También estaba considerando si la presencia de una lista explícita en la opción "types" en tsconfig.json no debería permitir el uso de UMD en un módulo. Significa que el tipo está presente deliberadamente. (Aunque obviamente no descarta el error de que olvidó importarlo).

O de manera similar, el uso de una construcción /// <reference types="..." /> debería permitir el uso de UMD de ese paquete en el módulo en el que se usa (es decir, el 'control por módulo' mencionado).

@RyanCavanaugh ¿Habrá una bandera para abordar el # 26233 también?

26233 se considera que funciona plenamente según lo previsto; acceder al lado de tipo de un UMD global desde un módulo es legítimamente inofensivo

No estoy muy seguro de si es "legítimamente inofensivo". Usando @types/jquery como ejemplo. $ y jQuery se asignan a la interfaz JQueryStatic y se exportan como constantes. Como resultado, todos los módulos pueden acceder a $ y jQuery sin importar. Espero poder desactivar eso.

@RyanCavanaugh sí, es inofensivo en el sentido de que la emisión de TS no se ve afectada por ella. Es problemático si desea un control detallado sobre a qué @types puede acceder cada biblioteca: está convirtiendo lo que al menos parece tipos de módulo con alcance en tipos globales. Ampliar el acceso también puede ser un problema, incluso si emit no se ve afectado.

En realidad, en el caso de jQuery, emit se ve afectado. $() se emite en un módulo sin una importación.

Aceptación de PR para una nueva bandera que permite el acceso a globales UMD desde todos los módulos.

En cuanto a la implementación, es bastante sencillo ... pero necesitamos nombrarlo. Lanzamos una docena de nombres terribles en la reunión de revisión de sugerencias y los odiamos a todos, por lo que depende de ustedes encontrar algo agradable. Por favor, deténgase.

Pateamos una docena de nombres terribles en la reunión de revisión de sugerencias y los odiamos a todos.

¿Que eran?

por lo que depende de todos ustedes encontrar algo agradable.

Quizás umdUseGlobal o algo así.

Sugeriría importAllNamespaces para el nombre de la bandera global de UMD porque los globales de UMD suelen ser export as namespace .

@RyanCavanaugh ¿El equipo discutió sobre el problema del tipo?

@FranklinWhale sí.

@saschanaz Ya lo @RyanCavanaugh ¿Recuerdas qué nombres terribles se discutieron?

Creo que la cadena fue algo como esto

  • allowUmdGlobalAccessFromModules - más preciso pero muuuucho largo
  • assumeGlobalUmd - ugh
  • allowModuleUmdGlobals - "globales" ??
  • umdAlwaysGlobal - 🤢
  • allowUmdGlobals - ¿pero ya puedo?
  • allowUmdGlobalAccess - se salta la parte del módulo, pero probablemente a nadie le importe.

Elegiría el último si me obligara a

¡Gracias!

Me gusta más allowUmdGlobalAccessFromModules porque, aunque es largo, su precisión hace que sea más fácil de recordar. Yo pensaría: "¿Cuál es esa opción que permite acceder a los globales UMD desde módulos? ¡Oh, sí, es allowUmdGlobalAccessFromModules , por supuesto!"

El uso del prefijo "permitir" coincide con la convención de nomenclatura de otras opciones, lo cual es bueno.

Además ... hay otras opciones que son tan largas :)

allowUmdGlobalAccessFromModules : 31 caracteres

allowSyntheticDefaultImports : 28 caracteres
strictPropertyInitialization : 28 caracteres
suppressExcessPropertyErrors : 28 caracteres
suppressImplicitAnyIndexErrors : 30 caracteres
forceConsistentCasingInFileNames : 32 caracteres

¿Cuál es la solución alternativa actual? He estado buscando en Google durante la última hora y no puedo encontrar ninguna solución viable.
Prefiero no pasar a 'cualquiera' o degradar a una versión de Typecript funcional, pero no puedo encontrar otras opciones.
¿Hay una compilación experimental en algún lugar que tenga una marca de compilador que solucione este problema?
(por cierto, 'allowUmdGlobalAccessFromModules' es un nombre excelente; no es como si lo escribiéramos 50 veces al día :-))

Estamos usando tsc 3.2.2 con lodash incluido estáticamente en el archivo HTML superior; con require.js; d.ts obtenido del último DefinitelyTyped; código de ejemplo que no se puede compilar:

/// <reference path="..." />

class Example<T extends IThingWithTitle<T>> {

    public test = (arg : T[]) : void => {
        _.sortBy(arg, (el : T) => { return el.title; }); // TS2686: '_' refers to a UMD global, but the current file is a module. Consider adding an import instead.
    };

}

export = Example;

(por favor, no me digas que necesito darle la vuelta al proyecto, sé que estamos detrás de la curva en algunos aspectos)

Actualización: ((ventana) ._) / * FIXME https://github.com/Microsoft/TypeScript/issues/10178 * /. sortBy (...) funciona pero querido Señor, es feo :-P

@Gilead , la solución de este comentario funciona bien por ahora: https://github.com/Microsoft/TypeScript/issues/10178#issuecomment -263030856

¿Hay algún progreso en esto? Tengo un caso en el que la solución alternativa mencionada no parece funcionar (usando [email protected] ) porque me encuentro con este problema.


Primero probé esto:

import 'firebase';

declare global {
  const firebase;
}

Esto le da implícitamente al firebase global el tipo any , y luego le aplica el espacio de nombres (con el mismo nombre). Primero, esto pareció funcionar porque muestra la información sobre herramientas / intellisense adecuados para todas las claves de nivel superior de firebase .

Sin embargo, en realidad no funciona (supongo que porque luego cambia a usarlo como tipo any , ¿lo que podría ser un error?):


Así que probé la solución alternativa mencionada aquí sin éxito (aunque funciona para otros):

import _firebase from 'firebase'; // same with = require('firebase') 

declare global {
  const firebase: typeof _firebase;
}

=> 'firebase' se hace referencia directa o indirectamente en su propia anotación de tipo.
(¿aunque el espacio de nombres tiene un alias?)


También lo intenté

import * as _firebase from 'firebase';

declare global {
  const firebase: typeof _firebase;
}

=> Definición circular del alias de importación '_firebase'.
(¿quizás debido a export = firebase; export as namespace firebase; en su definición ?)


Y finalmente, si hago el import 'firebase' , estoy de vuelta en

'firebase' se refiere a un UMD global, pero el archivo actual es un módulo. [2686]


Si alguien tiene una solución para esto, sería muy apreciada. De lo contrario, cualquiera de las sugerencias para resolver esto que se mencionaron hasta ahora me parece bien (bandera, referencia de barra diagonal triple, types en tsconfig, tener un objeto global o external en tsconfig).

Comentario de Re

¡Esto no puede permitir que todo esto haya estado en vena y vuelva a los globales!

No estoy tratando de volver a los globales, solo estoy tratando de que un par de dependencias pesadas se carguen por separado de mi paquete de aplicaciones, mientras sigo usando módulos para todo lo demás, porque trae algunos beneficios: las dependencias se pueden almacenar en caché correctamente porque no se actualizan con tanta frecuencia como mi paquete de aplicaciones; el tamaño de mi paquete no explota (a veces debido a la división del código, el paquete incluye la misma dependencia varias veces), lo que significa menos descargas para los usuarios de mi aplicación; reconstruir mis paquetes durante el desarrollo es mucho más rápido.

Esta es realmente una característica muy fácil de agregar; Sería genial que un miembro de la comunidad lo aceptara.

@RyanCavanaugh Lo miré y me di cuenta de que tengo que agregar la opción a compiler/types.ts y modificar el cheque global umd en compiler/checker.ts , y creo que necesito agregarlo a compiler/commandLineParser.ts también ... pero creo que me tomaría bastante tiempo hacerlo porque no estoy familiarizado con la fuente en absoluto (por ejemplo, ¿cómo agrego una descripción para la bandera CLI sin romper el i18n)? . Por ahora voy a esperar a que alguien más que conozca la fuente ya se encargue.

@simonhaenisch Puede declararlo en un archivo de declaración que no sea de módulo y, para evitar una referencia circular, puede reexportarlo en otra declaración de módulo UMD. El firebase se declara como un espacio de nombres, por suerte para nosotros, aumentará nuestra declaración, sin causar errores.

// umd.d.ts
import firebase = require("firebase");
export import firebase = firebase;
export as namespace UMD;

// global.d.ts
declare const firebase: typeof UMD.firebase;

Desafortunadamente, lo que declaramos es un valor, no un espacio de nombres, por lo que no puede hacer algo como let x: firebase.SomeInterface , la única forma de alias de un espacio de nombres es declarando una importación, pero no puede declare import firebase = UMD.firebase; , porque el espacio de nombres no lo aumentará. Claro que podemos usar un nombre diferente solo para namspace usando en tipo, pero eso causará confusión, prefiero eliminar el resto del código que hablé anteriormente, asignarlo a un valor global en tiempo de ejecución, hacer que el alias de importación realmente funcione.

Al igual que en el comentario anterior, estamos cargando de forma diferida hls.js (UMD) y tipos de referencia así:

En hls.d.ts :

import * as Hls from 'hls.js';
declare global {
    const Hls: typeof Hls;
}

En el archivo .ts usando el módulo UMD de carga diferida:

/// <reference path="hls.d.ts" />
// now use it
if(Hls.isSupported()){
 ...
} 

Probado en TypeScript> = 3.0.1 y 3.4.1.

El fundamento es la compatibilidad incompleta del navegador para las importaciones de módulos dinámicos.

@MatthiasHild ¿Se puede hacer sin el comentario /// <reference path="hls.d.ts" /> ?

EDITAR, sí, siempre que la declaración esté dentro de un archivo .d.ts incluido que NO tenga el mismo nombre que otro archivo .ts , basado en esta pregunta SO (eso es lo que me estaba dando y por qué pregunté).

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