Typescript: Considere permitir o acesso a globais UMD de módulos

Criado em 5 ago. 2016  ·  73Comentários  ·  Fonte: microsoft/TypeScript

O feedback do # 7125 é que algumas pessoas realmente misturam e combinam bibliotecas UMD globais e importadas, o que não consideramos um cenário provável ao implementar o recurso.

Três opções plausíveis:

  1. Faça o que fazemos hoje - ruim porque não há uma boa solução alternativa
  2. Permitir que alguma sintaxe ou configuração diga "este UMD global está realmente disponível globalmente" - um tanto complexo, mas factível
  3. Permitir acesso a todos os globais UMD, independentemente do contexto - erros perdidos onde as pessoas se esquecem de importar o global UMD em um arquivo. Estes são presumivelmente um tanto raros, mas seria estúpido perdê-los

Parece que funcionaria, mas provavelmente não:

  1. Sinalize os módulos UMD importados como "não disponíveis para global" - ruim porque os módulos UMD serão importados em arquivos de declaração durante o aumento do módulo. Seria estranho ter um comportamento diferente entre as importações de arquivos de implementação e arquivos de declaração.

Estou inclinado para a opção 3 para simplificar, mas poderia ver a opção 2 se houver alguma sintaxe ou configuração razoavelmente boa que possamos usar em um lugar lógico. Detectar o uso de um UMD global em uma regra TSLint seria simples se alguém quisesse fazer isso.

Um caminho a seguir seria implementar a opção 3 e, se acontecer que as pessoas cometam o erro "esqueci de importar" com freqüência, adicione uma opção tsconfig globals: [] que especifica explicitamente quais globais UMD são permitidos.

Add a Flag Committed Suggestion good first issue help wanted

Comentários muito úteis

+1 sobre isso. Eu estava tentando usar o React com SystemJS e, como o React não se agrupa muito bem, estou apenas carregando-o direto do CDN em uma tag de script e, portanto, os objetos React / ReactDOM estão disponíveis globalmente.

Estou escrevendo código como módulos como prática recomendada, mas isso será agrupado (Rollup) em um script de tempo de execução que executa no carregamento. É uma dor (e uma mentira) ter que import from react / react-dom e, em seguida, configurar o carregador para dizer "não realmente, são globais" (semelhante ao exemplo de configuração do WebPack fornecido em https: / /www.typescriptlang.org/docs/handbook/react-&-webpack.html). Seria muito mais fácil (e mais preciso) simplesmente tê-los disponíveis como globais em meus módulos. As etapas que tentei, por parecerem intuitivas, foram:

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

No entanto, isso resulta no erro React refers to a UMD global, but the current file is a module. Consider adding an import instead .

Se isso funcionasse, seria muito mais simples do que fingir no código que é um módulo e, em seguida, configurar o carregador / bundler de que não é. (Ou alternativamente, eu meio que fiz o que esperava adicionando um arquivo contendo o seguinte. Agora meus módulos podem usar React & ReactDOM como globais sem erros, mas é meio feio / hackeado - embora possa haver uma maneira mais simples de perdi):

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

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

Todos 73 comentários

Em vez de permitir o acesso a todos os globais UMD, independentemente do contexto, não seria mais simples permitir o acesso apenas ao global UMD se o módulo UMD fosse explicitamente "referenciado" (não importado) por meio da sintaxe ///<reference types=<>> , ou através da configuração types em tsconfig.json?

Em outras palavras, por que não permitir que ///<reference types=<>> seja usado em um módulo?

Se dissermos que /// <reference type="x" /> significa que x está disponível globalmente _todo lugar_, frequentemente será o caso de que algum arquivo .d.ts em algum lugar fará referência incorreta a coisas que não são realmente globais ( Posso dizer isso porque estou mantendo o branch 2.0 do DefinitelyTyped e é um erro extremamente comum).

Por outro lado, se estiver disponível apenas _nesse arquivo_, você terá que copiar e colar diretivas de referência em todos os lugares, o que é realmente irritante. Essas diretivas são normalmente idempotentes, portanto, introduzir um comportamento específico de arquivo é estranho.

Eu vejo. Bem, se isso não está afetando ninguém, talvez seja melhor manter o comportamento atual. Vou ter que fazer uma transição completa para importar coisas como módulos.

Edit: fico feliz em ver que isso afeta muitas pessoas além de mim.

A teoria atual é apenas pedir às pessoas que migrem para o uso de módulos ou não. Se outras pessoas se depararem com isso, deixe um comentário com exatamente quais bibliotecas você estava usando para que possamos investigar mais.

Estou usando o lodash, que não vem com tipificações próprias. Eu também tenho uma situação em que no meu ambiente de tempo de execução é mais fácil usar instruções de importação de caminho relativo. Portanto, tenho uma combinação de instruções de importação com caminhos relativos locais e parentes de pasta ('./foo' e também 'N / bar').

Se eu copiar manualmente @types/lodash/index.d.ts para node_modules/lodash/ , posso fazer com que as coisas sejam verificadas.

Até agora, minha solução alternativa estava usando ///<amd-dependency path='../lodash' name="_"> (e nenhuma instrução import ). Com esta combinação, as definições @ types / lodash seriam vistas 'globalmente' pelo compilador e ainda teriam o caminho relativo correto ( ../lodash ) no JS emitido.

Espero que este seja um cenário próximo o suficiente para este problema.

Você pode esclarecer

Eu também tenho uma situação em que no meu ambiente de tempo de execução é mais fácil usar instruções de importação de caminho relativo.

e

Se eu copiar manualmente @types/lodash/index.d.ts para node_modules/lodash/ , posso fazer com que as coisas sejam verificadas.

por favor? Não estou familiarizado com esse cenário, então qual é o propósito disso e por que ele é útil?

Oi pessoal,

Eu estou no processo de procura de uma solução para atual @types/bluebird declaração problema (por favor, não passar tempo de lê-lo). Descobri que o problema poderia ser resolvido adicionando export as namespace Promise; a .d.ts, mas então me deparei com o problema descrito por este problema do github.

Resumindo, gostaria que o seguinte funcionasse:

  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 adicionando export as namespace Promise; acima da linha export = Bluebird; .
  5. npm run tsc

Resultado atual:
Alguns erros de 'Promise' refers to a UMD global, but the current file is a module. Consider adding an import instead. .

Resultado esperado:
A compilação é bem-sucedida.

Este problema é particularmente difícil, porque é desencadeado pelo uso de Promise no código do desenvolvedor e no código de terceiros (RxJS nesse caso). O último assume que Promise é global (fornecido pelo padrão JS), portanto, nunca mudará para usar, por exemplo, import Promise from std; // (not that "std" is a thing) .

Eu realmente aprecio uma maneira de usar módulos UMD como módulos importáveis ​​e globais.

Obrigado.

----------------------------- Atualização

Acabei resolvendo esse problema de maneira diferente (a saber: por Promise e PromiseConstructor aumento das interfaces).

A opção "globals": [] tsconfig parece preferível a torná-los visíveis em todos os lugares. Com a declaração UMD se tornando a norma, as chances de se esquecer acidentalmente de importar um módulo são altas. Considere manter o comportamento atual. Isso deve ser um erro.

Curiosamente, lembro-me de quando o momento removeu sua variável global window.moment em um lançamento pontual. Achávamos que o havíamos importado criteriosamente para todos os lugares, mas nos esquecemos de cerca de 5 lugares.

É claro que um pacote UMD estará disponível no escopo global em tempo de execução, mas quando ele se torna disponível depende da ordem em que os outros módulos são carregados.

+1 sobre isso. Eu estava tentando usar o React com SystemJS e, como o React não se agrupa muito bem, estou apenas carregando-o direto do CDN em uma tag de script e, portanto, os objetos React / ReactDOM estão disponíveis globalmente.

Estou escrevendo código como módulos como prática recomendada, mas isso será agrupado (Rollup) em um script de tempo de execução que executa no carregamento. É uma dor (e uma mentira) ter que import from react / react-dom e, em seguida, configurar o carregador para dizer "não realmente, são globais" (semelhante ao exemplo de configuração do WebPack fornecido em https: / /www.typescriptlang.org/docs/handbook/react-&-webpack.html). Seria muito mais fácil (e mais preciso) simplesmente tê-los disponíveis como globais em meus módulos. As etapas que tentei, por parecerem intuitivas, foram:

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

No entanto, isso resulta no erro React refers to a UMD global, but the current file is a module. Consider adding an import instead .

Se isso funcionasse, seria muito mais simples do que fingir no código que é um módulo e, em seguida, configurar o carregador / bundler de que não é. (Ou alternativamente, eu meio que fiz o que esperava adicionando um arquivo contendo o seguinte. Agora meus módulos podem usar React & ReactDOM como globais sem erros, mas é meio feio / hackeado - embora possa haver uma maneira mais simples de perdi):

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

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

Também concordo com as três opções mais globais: [] backup. Isso parece muito intuitivo para usuários novos e antigos e forneceria a funcionalidade exata de que as pessoas precisam.

Não sou um especialista em código, então não posso dizer se 2 seria mais preferível ou não, mas acho que também seria intuitivo, pois a configuração é simples.

Se eu quiser buscar ajuda para implementar qualquer um desses, onde devo ir?

Isso realmente deveria estar atrás de uma bandeira. É um grande risco de refatoração. Mesmo se o sinalizador for especificado como verdadeiro por padrão. Acho que isso deve continuar a funcionar no cenário original, caso contrário, estaremos perdendo o benefício principal das declarações UMD.

React não agrega muito bem

@billti você pode elaborar?

É uma dor (e uma mentira) ter que import from react / react-dom e, em seguida, configurar o carregador para dizer "não realmente, estes são globais"

A única razão pela qual escrevi isso no tutorial é porque usar externals reduz o tempo do pacote. Se você usar a variável global React sem importar, não será possível alternar facilmente para os módulos mais tarde, enquanto as importações oferecem a flexibilidade de usar qualquer um deles, dado seu carregador.

Consulte este problema (https://github.com/rollup/rollup/issues/855) para ver um exemplo de como eles estão tentando otimizar o empacotamento e os tamanhos observados. Efetivamente na minha configuração (usando Rollup), vi ganhos de tamanho mínimos agrupando o React, então prefiro servir apenas de um CDN. Para mim, isso tem os benefícios de:

a) Menos solicitações (e largura de banda) para meu site.
b) Menos tempo para agrupar na minha cadeia de construção.
c) Menos código para baixar novamente no cliente toda vez que eu empurro uma alteração (já que apenas meu código está no pacote que é baixado novamente e o React ainda está no cache do cliente sem modificações - obtendo assim 304s).

Olhando nas ferramentas de desenvolvimento do Chrome ao carregar o site, React e React-dom (as versões reduzidas), em uma conexão HTTP GZipped, têm apenas 47kb de tráfego de rede, o que é menos do que a maioria das imagens em um site, então não preocupado em tentar reduzir tanto de qualquer maneira, a menos que haja ganhos realmente grandes a serem obtidos (por exemplo, redução de 50%).

Como um adendo: eu também observaria que, sem essa opção, você também está forçando as pessoas a usar um bundler que elimina essas importações, já que o compilador do TypeScript em si não tem configuração para dizer "este módulo é realmente global" e, portanto, emite importações (ou requer ou define) para módulos que não resolveriam em tempo de execução.

@billti SystemJS tem suporte total para este cenário. Você pode alternar entre o uso de um pacote instalado localmente durante o desenvolvimento e o uso de um CDN na produção. Ele também tem suporte total para metadados que especifica que todas as importações devem realmente indicar referências a uma variável global que será buscada uma vez e anexada ao objeto de janela quando necessário, na produção isso pode vir de um CDN. Não fiz isso com o react, mas fiz com o angular 1.x

Obrigado @aluanhaddad . Interessante ... Na verdade, eu estava tentando fazer algo parecido funcionar que me levou a esse obstáculo, mas não consegui descobrir, então esta manhã fiz a pergunta no repositório SystemJS. Se você puder responder como obter https://github.com/systemjs/systemjs/issues/1510, isso seria muito útil :-)

Nota: Meu outro comentário ainda permanece, que a emissão pelo próprio TypeScript não é utilizável sem isso, já que você precisa de algo como SystemJS / WebPack / Rollup etc ... para mapear as importações para globais para que o código seja executado.

Vou dar uma olhada e ver se consigo fazer um exemplo funcional, não faço isso há um bom tempo e não tenho acesso ao código-fonte que tinha na época, mas estou cem por cento certo é possível.

Em seu segundo ponto, isso é exatamente o que SystemJS faz. Ele mapeará essas importações para o global e entenderá que o global está realmente sendo solicitado e já foi carregado. A saída é definitivamente utilizável

Para sua informação: eu consegui trabalhar no SystemJS usando a API SystemJS e adicionei minha solução em https://github.com/systemjs/systemjs/issues/1510 . Obrigado.

Quanto ao meu segundo ponto: Sim, eu sei que é exatamente o que os carregadores podem fazer. Esse é o meu ponto, eles podem mapear um módulo importado para um global, mas o TypeScript não pode - então você tem que usar um carregador para tornar seu código válido em tempo de execução. Portanto, é um catch-22 com este problema original, onde você não pode declarar que o global (neste caso, React) está disponível no módulo, você tem que importá-lo como se fosse um módulo (o que não é) .

Meu outro comentário ainda permanece, que a emissão pelo próprio TypeScript não pode ser usada sem isso, já que você precisa de algo como SystemJS / WebPack / Rollup etc ... para mapear as importações para globais para o código ser executado.

@billti Eu não entendo. Qual é um cenário em que sua única opção é usar a versão global de um módulo, mas o TypeScript não permite que você faça isso? Eu só vi situações em que uma biblioteca está disponível tanto como um global e um módulo.

@DanielRosenwasser Acho que ele quer dizer que o React é na verdade um global em tempo de execução como um membro do objeto global, por causa de como está sendo carregado.

@billti Incrível que você fez isso funcionar.

Quanto ao seu segundo ponto: entendo o que você quer dizer.

Suponho que meu sentimento é que, em um cenário de navegador, porque você precisa usar um carregador como RequireJS ou um empacotador como Webpack porque nenhum navegador suporta módulos, ainda não faz nenhuma diferença. (Eu ouvi que Chakra tem disponível atrás de uma bandeira). Portanto, não há como executar o código sem uma ferramenta adicional. É uma espécie de implicação da saída contendo define , require ou System.register que o código _JavaScript_ emitido provavelmente não é portátil. No entanto, vejo a importância da distinção "módulo versus não um módulo".

Você pode usar esta solução alternativa para, pelo menos, referir-se ao "módulo" apenas uma vez.

_shims.d.ts_

import __React from 'react';

declare global {
  const React: typeof __React;
}

Depois, você pode usá-lo em qualquer outro lugar sem importá-lo.
Além disso, isso é bem explícito, embora um pouco confuso, porque você está dizendo que o React se tornou global e também é por isso que você não precisa mais importá-lo.

Re your shims.d.ts, se você subir alguns posts, verá que é o que fiz por agora (grandes mentes pensam da mesma forma) ;-)

Posso fazer funcionar de várias maneiras agora, esse não é o ponto. Estamos tentando tornar o TypeScript fácil de adotar e fazer com que os usuários caiam no poço do sucesso, não no poço do desespero. Com isso em mente, costumo me fazer duas perguntas ao tentar usar o TypeScript e encontrar problemas: a) Este código é válido eb) Os clientes tentarão fazer isso.

Vendo que eu tinha a versão (não TypeScript) fazendo o que eu queria no Babel quase no tempo que levei para digitá-la, acho que é justo dizer que o código é válido. Como a página de instalação dos documentos do React mostra como usar tags de script de um CDN para incluir o React, acho que várias pessoas também tentarão. (FWIW: Eu gastei mais tempo do que gostaria de lembrar trabalhando com vários módulos e carregadores JS, então não é como se eu não os conhecesse, eu só queria escrever meu código dessa forma).

Se o TypeScript não oferecer suporte a certos padrões válidos de escrita de código, devemos tentar tornar isso imediatamente óbvio e orientar as pessoas da maneira certa (o que é um desafio em mensagens de erro ou documentos concisos). Mas, pessoalmente, não acho que o TypeScript não deva oferecer suporte a padrões, porque não os consideramos "melhores práticas" ou "canônicos". Se o código for válido e alguns desenvolvedores de JavaScript quiserem escrevê-lo, o TypeScript deve tentar suportá-lo. Quanto mais exigirmos que eles alterem seu código e reconfigurem seu pipeline de construção para fazer o TypeScript funcionar (como é recomendado aqui para migrar meu aplicativo trivial), menos desenvolvedores serão transferidos.

Quanto à solução ... apenas cuspindo aqui, mas talvez a opção de compilador "lib", que já define efetivamente quais APIs estão disponíveis em todo o projeto, também poderia levar @types/name valores de formato para bibliotecas para adicionar globalmente (e até mesmo suportar caminhos relativos, talvez).

Estamos tentando tornar o TypeScript fácil de adotar e fazer com que os usuários caiam no poço do sucesso, não no poço do desespero.

Eu acho que nós estamos tentando levar os usuários a boca do sucesso agora. Se um módulo define apenas condicionalmente um global, você está acidentalmente guiando os usuários a usar algo que não existe. Portanto, vejo algumas opções diferentes:

  1. Crie uma construção export as namespace foo aumentada que só é visível se não for importada por um módulo.
  2. Não faça nada e continue pressionando as pessoas a usarem a importação - isso é mais ou menos bom na minha opinião, uma vez que tornamos a mensagem de erro razoavelmente prescritiva de qualquer maneira.
  3. Permitir que as pessoas usem o UMD de qualquer lugar - honestamente, não sou tão fã dessa ideia.

@billti

Re your shims.d.ts, se você subir alguns posts, verá que é o que fiz por agora (grandes mentes pensam da mesma forma) ;-)

Desculpe, eu perdi isso, muito bom;)

Não acho que o TypeScript não deva oferecer suporte a padrões, porque não os consideramos "melhores práticas" ou "canônicos"

Não acho que o TypeScript esteja sendo proscritivo aqui, acho que está fazendo o que afirma, me informando que tenho um erro. Muitas bibliotecas têm demos e tutoriais em que se carregam como globais e, em seguida, usam a sintaxe do ES Module. Eu não acho que eles estão sendo os maiores cidadãos fazendo isso, mas essa é outra discussão.

Dito isso, se os módulos são usados ​​principalmente como um açúcar sintático _percebido_ sobre os globais, então seu fracasso está próximo porque eles não são um açúcar sintático de forma alguma. No mínimo, eles são um sal sintático (talvez um imposto?) Que consumimos para obter benefícios como verdadeiro isolamento de código, liberdade de marcação de script, declaração de dependência explícita, fuga do inferno do namespace global e outros benefícios. A sintaxe dos módulos não é ergonômica, é prolixo, na melhor das hipóteses, mas é a semântica dos módulos que faz com que valha a pena.

Acho que se as pessoas usarem o TypeScript, pelo menos em arquivos .ts , suponho que desejam obter os benefícios de uma forte análise de código estático. Babel não faz isso, presumindo que React existe, mas não tendo conhecimento disso. Isso é verdade, embora os Módulos ES tenham sido deliberadamente especificados para serem passíveis de análise estática.

@DanielRosenwasser

Crie uma exportação aumentada como construção de namespace foo que só é visível se não for importada por um módulo.

Essa parece ser a melhor maneira de resolver isso.

Aqui está outro caso em que isso causou problemas:

Em um projeto no qual estou trabalhando atualmente, misturamos inclui locais (principalmente por motivos históricos) com módulos npm. No final, tudo é unido usando Rollup ou Browserify, então tudo bem.

Eu uso um arquivo .js do projeto emojione que simplesmente copiei para a base de código. Mais tarde, adicionei as declarações de tipo para ele ao DefinitelyTyped: https://github.com/DefinitelyTyped/DefinitelyTyped/pull/13293 Pensei que agora poderia simplesmente carregar os tipos e tudo funcionaria. Mas não parece ser o caso, porque o TypeScript não me deixa acessar o global.

O motivo pelo qual não estou mudando para o módulo npm é que o módulo npm também agrupa vários megabytes de sprites e PNGs. Eu só preciso de um script de 200 KiB. Com declarações de tipo.

Com o AngularJS, a solução alternativa foi declare var angular: ng.IAngularStatic . Mas isso não funciona com namespaces, certo?

@dbrgn Você está tendo um problema diferente. Se o módulo for realmente global, sua definição de tipo está incorreta. Ele não declara um global, nem é uma declaração de estilo UMD (trata-se de declarações de estilo UMD); na verdade, ele declara apenas um Módulo ES puro.

Se o módulo representar um global, não exporte no nível superior do arquivo, isso o torna um módulo.

Com o AngularJS, a solução alternativa foi declarar var angular: ng.IAngularStatic. Mas isso não funciona com namespaces, certo?

Funciona com namespaces.

O resultado da discussão em nossa reunião de design foi que estamos considerando sempre permitir o UMD e adicionar um sinalizador que reforce a restrição atual. A restrição também será estendida para trabalhar em tipos de acesso de um UMD global.

Tendo pensado mais sobre isso, ainda acho que a melhor coisa a fazer é criar um novo tipo de declaração. Este sinalizador é menos detectável do que a nova sintaxe, que só precisa ser escrita uma vez pelo autor do arquivo de declaração.

Isso é desesperadamente necessário para códigos e ferramentas existentes. Até que o Javascript pare de funcionar rapidamente e perca os sistemas de módulo, precisamos de flexibilidade para trabalhar com o código que existe. Emita um aviso, mas não falhe na construção. Perdi dias tentando fazer o código legado funcionar bem com rollup e texto digitado.

UGH.

Eu sei que há muitas pessoas que gostam de rir de Java, mas os módulos Java básicos pelo menos funcionam. Potes de trabalho

Não tenho que ajustar 14 padrões de módulo ad hoc diferentes, ou tentar compilar um módulo js de arquivos de origem no formato que a ferramenta de rollup / empacotamento do dia irá realmente consumir sem fazer cocô e também irá gerar um formato de módulo que funcionará bem com instruções de importação / exportação do Typescript e arquivos d.ts de terceiros para que o TSC decida realmente construir o código em vez de reclamar de algo para onde você está indo "APENAS USE A IMPORTAÇÃO DARN, SERÁ UM AT GLOBAL TEMPO DE EXECUÇÃO".

O hack shims.d.ts funciona bem. Mas ugh.

Solução temporária para quem usa Webpack https://github.com/Microsoft/TypeScript/issues/11108#issuecomment -285356313

Adicione externals a webpack.config.js com os globais UMD desejados.

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

Acho que isso deve ser possível para facilitar a migração de bases de código existentes.

Tenho um projeto implementado com requirejs onde o jQuery é incluído como global, porque existem alguns plug-ins que estendem o jQuery apenas se for encontrado como global.

O código em alguns dos módulos depende desses plugins, que não estariam disponíveis se o jQuery fosse importado como um módulo. Para fazer isso funcionar, eu teria que modificar todos os plugins para funcionar com o jQuery carregado como um módulo, carregando-os também como módulos (uma adivinhação de onde eles são necessários).

Além disso, também existem páginas que usam javascript sem carregadores de módulo. Portanto, os plug-ins devem funcionar tanto com globais quanto com módulos.

Além do jQuery, existem outros scripts com o mesmo problema, como knockout e outros. Isso torna a migração do projeto um pesadelo. Ou, do ponto de vista realista, inviável.

Claro, esse não é o melhor padrão e eu não o usaria em um novo projeto. Mas eu não acho que sou o único com esse problema

Faria sentido usar types em tsconfig.json para isso? Por exemplo, sem types set, você obtém o comportamento implícito atual e com types set, você está literalmente dizendo "essas coisas são globais" e pode forçar o namespace UMD a aparecer globalmente. Esse é o tipo de comportamento que existe hoje de qualquer maneira (sem a força global). Isso se opõe à introdução de uma nova opção globals .

Acho que é uma boa ideia. No meu caso, existem scripts que usam uma biblioteca UMD como global e outras como módulo. Eu poderia resolver esse problema com dois tsconfig.json diferentes que tratam de cada caso. Realmente direto.

@blakeembrey Embora usar types faça sentido, não estou muito interessado na ideia de sobrecarregá-lo, pois já tem problemas. Por exemplo, a construção <reference types="package" /> já tem a limitação de não suportar "paths" . O "package" deve se referir a um nome de pasta em @types

Estou tendo dificuldades para acompanhar essa conversa. Houve alguma atualização ou resolução planejada para isso? Parece que isso é algo que pode ser útil em cenários como quando o lodash é uma parte integrante de um aplicativo ou quando mais bibliotecas de terceiros são convertidas para uma estrutura mais modularizada em vez de depender apenas de estar na janela.

Existe uma maneira planejada de resolver isso ou pelo menos documentar como isso deve ser resolvido com a versão atual disponível?

Olá @mochawich , estou recebendo o seguinte erro ao usar a definição do React como externo e não usar a sintaxe declare global :

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

@cantux TypeScript não lê a configuração do Webpack. Se você disponibilizou o React globalmente, pode declare isso, mas por que não usar módulos?

@aluanhaddad principalmente porque me confundi com o trabalho feito pelo import call. Eu mexi um pouco, as afirmações a seguir estão corretas?

Estamos pagando a pequena taxa de fazer uma solicitação quando importamos um módulo. Isso garante que o que estamos usando está disponível na memória, se foi solicitado anteriormente, o módulo é carregado do cache, se o módulo não existe, ele é buscado. Se você quiser contornar essa solicitação, basta definir algo como global e o Typescript confia cegamente em que está disponível (e se você usar um smart bundler import, as instruções podem até ser substituídas / removidas).

Se estiverem corretos, poderíamos remover os comentários para abreviar, o tópico é um gigante como está.

Como @codymullins perguntou acima, alguém pode resumir a solução alternativa atual para esse problema? Acabei de atualizar a definição do tipo de lodash e recebi muitos erros do TS2686.

Minha solução atual era hackear o arquivo typedef para se adequar ao antigo padrão de trabalho, mas isso não é viável se mais arquivos typedef começarem a quebrar.

Meu cenário é o seguinte:

  • em meus aplicativos de página única, eu importo várias bibliotecas (incluindo lodash) em um

o exemplo de shim mencionado acima funciona, embora vscode esteja destacando-o como um erro (embora ainda execute a conclusão corretamente!)

Por favor, não forneça erros ao acessar globais UMD em módulos. O enorme projeto no qual estou trabalhando é feito em AngularJS e estamos usando Typescript para o aplicativo, mas é claro que precisamos do Typescript para saber sobre os tipos globais e angulares angular UMD de @types/angular . Você pensaria que seria tão fácil quanto adicionar "angular" a types em tsconfig.json , mas, por alguma razão, não é, e o TSC grita comigo. Por mais que eu desejasse que todos os pacotes NPM fossem puro Typescript, a maioria deles são JS simples e o serão por muito tempo. Eu realmente não entendo porque o TSC não pode simplesmente calar a boca quando importamos um d.ts dizendo que um UMD global está presente. Essa situação é mais do que comum - todo projeto Typescript em que já trabalhei usa pelo menos uma biblioteca JS que preciso agrupar e fazer referência usando definições de tipo.

Existe alguma atualização sobre isso?

Meu caso de uso: Estou trabalhando em uma grande base de código existente que faz uso intenso de CDNs. Utilitários comuns são importados por meio de tags de script em muitas páginas (por exemplo, clipboardjs, lodash). Gostaria de fazer referência a essas variáveis ​​globais, uma vez que estão disponíveis na página. Sem usar módulos, é fácil compilar o typescript, usando /// <reference type="$name" /> no topo dos arquivos de origem relevantes. No entanto, isso para de funcionar ao tentar criar módulos.

Parece que houve duas abordagens propostas no tópico:

  1. Tenha os tokens de importação /// <reference type="$name" /> apenas no namespace do arquivo atual.

  2. Uma opção / variável de configuração do compilador em tsconfig.json (ex. "globals" , "types" )

Acho que ambas as abordagens são boas. Embora eu concorde com a crítica da opção 1 por @RyanCavanaugh :

Por outro lado, se ele estiver disponível apenas naquele arquivo, você terá que copiar e colar diretivas de referência em todos os lugares, o que é realmente irritante.

Eu acredito que é muito mais irritante que você não possa usar módulos com UMD globais devido ao comportamento atual. Alguma solução alternativa é melhor do que nenhuma.

Este problema ainda está pendente? E em caso afirmativo, qual é a solução alternativa atual?

Se você instalar o pacote @types , os pacotes que não são importados como módulos são disponibilizados como globais.

Por exemplo, se eu npm install -D @types/underscore na raiz do meu projeto, posso escrever módulos que não importam nada do sublinhado, mas o _ global é disponibilizado (veja abaixo).

types-ref

É isso que você quer?

@billti Talvez eu esteja entendendo mal, mas seu exemplo não funciona para mim.

Mínimo necessário para reproduzir:

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"
    ]
}

Mensagens de erro:

js / foo.ts (7,3): erro TS2686: 'Cookies' se refere a um UMD global, mas o arquivo atual é um módulo. Considere adicionar uma importação.
js / foo.ts (10,15): erro TS2686: 'Cookies' se refere a um UMD global, mas o arquivo atual é um módulo. Considere adicionar uma importação.
js / foo.ts (15,14): erro TS2686: 'Cookies' se refere a um UMD global, mas o arquivo atual é um módulo. Considere adicionar uma importação.

O comportamento que você obtém depende se o módulo importado foi escrito como um módulo UMD "adequado" (este é o comportamento com "Cookies") ou um módulo "funciona nos dois sentidos ao mesmo tempo" (que é como o lodash é escrito) .

A inconsistência de pessoas escrevendo corretamente um arquivo .d.ts que descreve como o objeto funciona em tempo de execução, e a opacidade da experiência para desenvolvedores, é o motivo pelo qual estou me inclinando muito na direção de "remover a restrição global UMD". Poderíamos colocá-lo em --strict com um cancelamento de --noStrictUMD .

A outra coisa que encontrei foi lidar com o carregador AMD personalizado do Monaco. Eles suportam alguns subconjuntos de comportamento AMD (insira um enorme eyeroll), mas pise no global 'require', então é realmente difícil usar módulos UMD adequados com ele, uma vez que esses módulos tendem a ver o 'require' global e, em seguida, não conseguem carregar corretamente no Carregador de módulo Monaco. Você acaba colocando as bibliotecas UMD JS acima da tag de script para o carregador Monaco e, em seguida, o TS reclama porque está acessando os globais de um módulo (que deve ser para importar as APIs Monaco).

@RyanCavanaugh

A outra coisa que encontrei foi lidar com o carregador AMD personalizado do Monaco. Eles suportam alguns subconjuntos de comportamento AMD (insira um enorme eyeroll), mas pise no global 'require', então é realmente difícil usar módulos UMD adequados com ele, uma vez que esses módulos tendem a ver o 'require' global e, em seguida, não conseguem carregar corretamente no Carregador de módulo Monaco.

😁

Alguma chance deles consertar isso?

Tenho pensado muito sobre o custo da complexidade dos módulos recentemente. Muitos carregadores, bundlers, transpilers, gerenciadores de pacotes e estruturas interdependentes e parcialmente compatíveis representam uma quantidade realmente não trivial de complexidade de acreditação. (Tenho certeza de que você não precisa de nenhum lembrete 🙉).

Como desenvolvedores, aceitamos cadeias de ferramentas que são ordens de magnitude mais complexas do que há 5 a 6 anos, e a fonte primária de complexidade tem sido os módulos.

Se desistirmos e começarmos a carregar esses pacotes UMD como globais, para que tudo isso terá servido?

E ainda assim ... as pessoas estão fazendo exatamente isso. Isso é terrível!

Quer dizer, esta Resposta Stack Overflow tem 61 👍s e tem sugerido todas as coisas erradas para 99% dos pacotes no último semestre. (o autor gentilmente o atualizou para mencionar os módulos como uma _opção_ para dependências UMD devido a alguns comentários fornecidos esta manhã)

Isso não pode deixar tudo isso estar na veia e voltar aos globais!

E ainda assim ... as pessoas estão fazendo exatamente isso. Isso é terrível!

O problema é que os módulos JS são terrivelmente mal concebidos e implementados, então é muito melhor e mais fácil voltar a usar globais. Se os módulos tivessem sido devidamente projetados e implementados desde o início ...

Nós misturamos e combinamos módulos e UMD globais porque é muito incômodo carregar nossas dependências como módulos com vários níveis de compatibilidade com vários carregadores e alguns carregadores que não suportam agrupamento de dependências diretas e, em vez disso, você tem que usar nosso pré-processador especial que leva um minuto para correr.

Esse "recurso" significa apenas que não usamos o suporte oficial do módulo UMD, embora realmente usemos módulos UMD. Apenas exportamos como um global do arquivo .d.ts e, em seguida, temos manualmente nosso próprio módulo com esse nome que reexporta tudo.

alguma atualização disso? Eu realmente gostaria que a opção 2 funcionasse:

Permitir que alguma sintaxe ou configuração diga "este UMD global está realmente disponível globalmente"

Também não ajuda que existam tantos js libs ao estilo da velha escola
lá, e reescrevê-los todos está fora de questão. Apenas trabalhando em um sólido
config para fazer o Rollup lidar com todos eles corretamente desperdiça horas do meu tempo.

As pessoas riem de "Enterprise Java", mas o Java simples vem com um viável
sistema de módulos em 1.0. Não era perfeito, mas não era uma bagunça completa.

Como é "Permitir globais de estilo UMD" definitivamente deve ser uma opção.

Na segunda-feira, 2 de abril de 2018 à 1h40 Kagami Sascha Rosylight <
notificaçõ[email protected]> escreveu:

Eu tive que contornar com:

/ * módulo: es2015 * /
// js-yaml suporta UMD, mas não o módulo ES2015! import * as _jsyaml de "js-yaml"; declare var jsyaml: typeof _jsyaml; jsyaml.safeLoad ("");

-
Você está recebendo isso porque comentou.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/Microsoft/TypeScript/issues/10178#issuecomment-377885832 ,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/AA50ljAD33sr09EGFVAsURbu1x75X-lOks5tkeQCgaJpZM4Jd8jX
.

>

Daniel Joyce

Os mansos herdarão a Terra, pois os bravos estarão entre as estrelas.

Estou usando three.js em um projeto Angular. Eu importo como

import * as THREE from "three";

import {Vector3} from "three"; também funciona conforme o esperado.

Com os pacotes three e @types/three npm instalados, tudo funciona bem. Por baixo do capô, acho que isso está usando three/build/three.module.js . O arquivo @types/three/index.d.ts usa a notação export as namespace THREE , com a qual não estou totalmente confortável, mas funciona.

Nesse caso específico, o problema é que há outro arquivo relacionado no sistema three.js chamado OrbitControls.js (que permite girar imagens 3D com o dedo ou mouse, basicamente). O problema é que embora esta função seja semioficialmente parte da distribuição three.js, é um arquivo JS simples encontrado na árvore examples e se posiciona diretamente na propriedade THREE da janela e usa diretamente outras APIs que espera encontrar presentes em window.THREE . Portanto, mesmo que eu "exija" o arquivo com

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

ele não consegue encontrar window.THREE para se colocar ou para acessar outras partes do TRÊS sistema que usa. Posso incluir a biblioteca inteira diretamente usando a propriedade Angular scripts em angular.json (aproximadamente equivalente a uma tag <script> antiquada), mas se não estou enganado, terá carregado a biblioteca duas vezes.

Para evitar isso, removi a instrução import * as THREE from "three"; e, ei, ela ainda pode resolver tipos como foo: THREE.Vector3 , mas engasga com referências como new THREE.Vector3() com o infame

'THREE' refere-se a um UMD global, mas o arquivo atual é um módulo. Considere adicionar uma importação. [2686]

Neste ponto, estou pensando que vou ter que pegar o arquivo OrbitControls.js e ES6-ify e / ou TS-ify, que é o que parece que mais do que outra pessoa já fez a forma de coisas como `orbit-controls-es6 , então talvez eu deva apenas simplificar minha vida e usar isso, embora eu odeie colocar minha vida nas mãos de outras pessoas dessa forma.

Em uma nota semi-não relacionada, uma estranheza é que @types/three define tipos para OrbitControls , mesmo que o próprio código não esteja no módulo three si. No entanto, não consigo descobrir como associar todos aqueles tipos que definem uma classe chamada OrbitControls com nada - gostaria de declarar a exportação padrão do orbit-controls-es6 mencionado acima

A solução que finalmente encontrei, da qual estou profundamente envergonhado, é:

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

Funciona, embora eu esteja um pouco confuso por quê. O arquivo necessário possui uma linha como

THREE.OrbitControls = funtion() { };

que parece que acabaria sendo atribuído aos TRÊS "namespaces" resultantes da instrução import * as THREE from "three"; , que não deveria funcionar, deveria?

@RyanCavanaugh me pediu para copiar meu feedback de # 26223 aqui:

Estou mantendo uma base de código TypeScript bastante grande (o monorepo interno do Google) que tem várias bibliotecas definitivamente tipadas das quais as pessoas dependem. Originalmente, os usuários dependiam apenas de tipos globais para bibliotecas como angular , antes que .d.ts fossem transformados em módulos externos. Em seguida, migramos a base de código para usar módulos e importações explícitas. Na verdade, esperávamos que export as namespace d globais UMD sempre exigiriam uma importação explícita para usar símbolos, para referências de tipo e valor, e nem mesmo percebemos quando migramos (opa).

Permitir o uso de código não importado geralmente é problemático para nós:

  • isso significa que o código depende de definições de tipo de "plano de fundo" globais, tornando o código mais difícil de ler (em particular em navegadores repo ou revisão de código sem ir para o símbolo).

  • obscurece as dependências do código

  • ele contorna as restrições "deve ter dependência de nível de construção explícita em todas as importações" que implementamos no bazel, também conhecidas como "dependências estritas".

    Em uma grande base de código, seu código deve ter dependências explícitas, caso contrário, o repo se tornará impossível de gerenciar. Agora, se você tem uma dependência chaing A -> B -> C e tipos globais, é fácil ter o código A compilado apenas porque B tem uma dependência de C . Se B posteriormente remover sua dependência, ele quebra A , o que significa que as alterações têm efeito cascata inesperado no repositório, violando o isolamento do código.

  • faz com que o código importe inconsistentemente o módulo com um prefixo para valores e use seus tipos com outro prefixo (em particular para AngularJS, ng vs angular)

Podemos contornar isso removendo as instruções export as namespace nossa cópia do DefinitelyTyped vendida, mas, pelo menos para nós, esse recurso funciona contra a capacidade de manutenção do código e nossos objetivos de engenharia. Acho que os problemas são mais pronunciados em uma situação monorepo como o Google, mas geralmente também se aplicam a bases de código menores.

Os pontos que você postou são absolutamente irrelevantes para a nossa situação. Somos forçados a implementar nosso próprio código com módulos AMD e fornecer nossas dependências com módulos UMD devido a circunstâncias que estão amplamente fora de nosso controle (mas eu resumiria como os módulos JS sendo terrivelmente falhos tanto no conceito quanto na implementação). Esse recurso nos permitiria simplificar consideravelmente nossas vidas.

Possivelmente com o TS3 poderíamos descobrir como evitar isso, mas mesmo se o fizéssemos, provavelmente levaria pelo menos dois anos antes de terminarmos todas as mudanças necessárias, então este ainda seria um recurso muito útil para nós.

Pergunta aberta: um sinalizador global para "Permitir acesso a todos os módulos UMD" seria suficiente ou as pessoas realmente precisam de controle por módulo sobre o erro?

Vote ❤️ para "apenas uma bandeira"
Vote 🎉 para "necessidade de controle por módulo"

Também estava considerando se a presença de uma lista explícita na opção "types" em tsconfig.json também não deveria permitir o uso de UMD em um módulo. Isso significa que o tipo está presente deliberadamente. (Embora obviamente não exclua o erro de que você se esqueceu de importá-lo).

Ou similarmente, usar uma construção /// <reference types="..." /> deve permitir o uso de UMD desse pacote no módulo em que é usado (isto é, o 'controle por módulo' mencionado).

@RyanCavanaugh Haverá uma bandeira para o endereço # 26233 também?

26233 é considerado funcionando totalmente como pretendido; acessar o lado do tipo de um UMD global a partir de um módulo é legitimamente inofensivo

Não tenho certeza se é "legitimamente inofensivo". Usando @types/jquery como exemplo. $ e jQuery são mapeados para a interface JQueryStatic e exportados como constantes. Como resultado, todos os módulos podem acessar $ e jQuery sem uma importação. Espero poder desabilitar isso.

@RyanCavanaugh sim, é inofensivo no sentido de que a emissão da TS não é afetada por ela. É problemático se você deseja um controle refinado sobre o que @types cada biblioteca pode acessar - está transformando o que pelo menos se parece com tipos de escopo de módulo em tipos globais. A ampliação do acesso também pode ser um problema, mesmo que a emissão não seja afetada.

Na verdade, no caso do jQuery, o emit é afetado. $() é emitido em um módulo sem importação.

Aceitando PRs para um novo sinalizador que permite acesso a globais UMD de todos os módulos.

Em termos de implementação, é bastante simples ... mas precisamos nomeá-lo. Chutamos cerca de uma dúzia de nomes terríveis na reunião de revisão de sugestões e odiamos todos eles, então cabe a vocês inventar algo palatável. Por favor, pare.

Chutamos cerca de uma dúzia de nomes terríveis na reunião de revisão de sugestões e odiamos todos eles

Quais foram eles?

então cabe a vocês inventar algo palatável.

Talvez umdUseGlobal ou algo assim.

Eu sugeriria importAllNamespaces para o nome da bandeira global UMD porque globais UMD geralmente são export as namespace .

@RyanCavanaugh A equipe discutiu sobre o tipo de problema?

@FranklinWhale yes.

@saschanaz Já perguntou isso, mas também estou curioso ... @RyanCavanaugh Você se lembra que nomes terríveis foram discutidos?

Eu acho que a corrente foi mais ou menos assim

  • allowUmdGlobalAccessFromModules - mais preciso, mas tãããão longo
  • assumeGlobalUmd - ugh
  • allowModuleUmdGlobals - "globais" ??
  • umdAlwaysGlobal - 🤢
  • allowUmdGlobals - mas eu já posso?
  • allowUmdGlobalAccess - pula a parte do módulo, mas provavelmente ninguém se importa?

Eu escolheria o último se fosse forçado a

Obrigado!

Gosto mais de allowUmdGlobalAccessFromModules porque, embora seja longo, sua precisão o torna mais fácil de lembrar. Eu pensaria: "Qual é a opção que permite que globais UMD sejam acessados ​​a partir de módulos? Sim, é allowUmdGlobalAccessFromModules , claro!"

Usar o prefixo "permitir" corresponde à convenção de nomenclatura de outras opções, o que é bom.

Além disso ... existem outras opções que são quase tão longas :)

allowUmdGlobalAccessFromModules : 31 caracteres

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

Qual é a solução alternativa atual? Tenho pesquisado no Google há uma hora e não consigo encontrar nenhuma solução viável.
Prefiro não lançar para 'qualquer' ou fazer o downgrade para uma versão de texto digitada em funcionamento, mas não consigo encontrar nenhuma outra opção.
Existe uma compilação experimental em algum lugar que tenha um sinalizador do compilador que corrige esse problema?
(a propósito, 'allowUmdGlobalAccessFromModules' é um nome excelente; não é como se o estivéssemos digitando 50 vezes por dia :-))

Estamos usando o tsc 3.2.2 com lodash estaticamente incluído no arquivo HTML principal; com require.js; d.ts obtidos no último DefinitelyTyped; código de exemplo que falha ao 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, não me diga que preciso virar o projeto de cabeça para baixo, sei que estamos atrasados ​​em alguns aspectos)

Atualização: ((window) ._) / * FIXME https://github.com/Microsoft/TypeScript/issues/10178 * /. sortBy (...) funciona, mas querido Senhor, é feio :-P

@Gilead , a solução deste comentário funciona perfeitamente por enquanto: https://github.com/Microsoft/TypeScript/issues/10178#issuecomment -263030856

Existe algum progresso nisso? Eu tenho um caso em que a solução alternativa mencionada parece não funcionar (usando [email protected] ) porque estou tendo esse problema.


Primeiro eu tentei isso:

import 'firebase';

declare global {
  const firebase;
}

Isso dá implicitamente ao firebase global o tipo any e, em seguida, aplica o namespace (com o mesmo nome) a ele. Em primeiro lugar, isso pareceu funcionar porque mostra as dicas de ferramenta / intellisense adequadas para todas as chaves de nível superior de firebase .

No entanto, ele realmente não funciona (presumo porque ele passa a usá-lo como tipo any , o que pode ser um bug?):


Então, tentei a solução alternativa mencionada aqui, sem sucesso (mas funciona para outros):

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

declare global {
  const firebase: typeof _firebase;
}

=> 'firebase' é referenciado direta ou indiretamente em sua própria anotação de tipo.
(mesmo que o namespace seja um alias?)


Eu também tentei

import * as _firebase from 'firebase';

declare global {
  const firebase: typeof _firebase;
}

=> Definição circular do alias de importação '_firebase'.
(talvez por causa de export = firebase; export as namespace firebase; em sua definição ?)


E, finalmente, se eu apenas fizer import 'firebase' , estou de volta

'firebase' se refere a um UMD global, mas o arquivo atual é um módulo. [2686]


Se alguém tiver uma solução para isso, ficaria muito grato. Caso contrário, qualquer uma das sugestões para resolver isso que foram mencionadas até agora me parecem realmente boas (sinalização, referência de barra tripla, types em tsconfig, tendo um objeto global ou external em tsconfig).

Comentário de Re

Isso não pode deixar tudo isso estar na veia e voltar aos globais!

Não estou tentando voltar aos globais, estou apenas tentando carregar algumas dependências pesadas separadamente do meu pacote de aplicativos, enquanto ainda uso módulos para todo o resto, porque traz alguns benefícios: as dependências podem ser armazenadas em cache corretamente porque eles não são atualizados com tanta frequência quanto meu pacote de aplicativos; o tamanho do meu pacote não explode (às vezes, devido à divisão de código, o pacote inclui a mesma dependência várias vezes), o que significa menos download para os usuários do meu aplicativo; reconstruir meus pacotes durante o desenvolvimento é muito mais rápido.

Este é realmente um recurso muito fácil de adicionar; seria ótimo para um membro da comunidade aceitá-lo.

@RyanCavanaugh Eu olhei para isso e meio que descobri que tenho que adicionar a opção a compiler/types.ts e modificar a verificação global umd em compiler/checker.ts , e acho que preciso adicioná-la a compiler/commandLineParser.ts também ... mas acho que demoraria um pouco para fazer isso porque não estou familiarizado com a fonte (por exemplo, como faço para adicionar uma descrição para o sinalizador CLI sem quebrar o i18n) . Por enquanto, vou esperar por alguém que já conhece a fonte para assumir.

@simonhaenisch Você pode declará-lo em um arquivo de declaração não-módulo e, para evitar a referência circular, pode reexportá-lo em outra declaração de módulo UMD. O firebase é declarado como um namespace, para nossa sorte, ele aumentará nossa declaração, não causando erros.

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

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

Infelizmente, o que declaramos é um valor, não um namespace, então você não pode fazer algo como let x: firebase.SomeInterface , a única maneira de criar um alias para um namespace é declarando uma importação, mas você não pode declare import firebase = UMD.firebase; , porque o namespace não o aumentará. Claro que podemos usar um nome diferente apenas para namspace usando in type, mas isso vai causar confusão, prefiro descartar o resto do código que falei acima, atribuí-lo a um valor global em tempo de execução, fazer o alias de importação realmente funcionar.

Semelhante ao comentário anterior, somos hls.js (UMD) de carregamento lento e tipos de referência assim:

Em hls.d.ts :

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

No arquivo .ts usando o módulo UMD carregado lentamente:

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

Testado em Typescript> = 3.0.1 e 3.4.1.

O Rationale é o suporte do navegador incompleto para importações de módulo dinâmico.

@MatthiasHild Isso pode ser feito sem o comentário /// <reference path="hls.d.ts" /> ?

EDITAR, sim, pode, contanto que a declaração esteja dentro de um arquivo .d.ts incluído que NÃO tenha o mesmo nome de outro arquivo .ts , com base nesta pergunta do SO (isso é o que estava me levando e por que eu perguntei).

Esta página foi útil?
0 / 5 - 0 avaliações