Typescript: Permitir que as definições do módulo sejam declaradas como variáveis ​​globais

Criado em 15 mai. 2015  ·  11Comentários  ·  Fonte: microsoft/TypeScript

Eu tenho o arquivo de definição de tipo React (que é declarado usando um módulo externo). Em meus arquivos de origem, geralmente faço:

import * as R from "react"

e pode então usar R.createElement(... etc alegremente de uma forma fortemente tipada. Eu posso até fazer:

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

O que eu quero é não ter que importar R em todos os arquivos e, em vez disso, tê-lo como uma declaração global (sim, estou disposto a poluir o namespace global com algumas variáveis). Eu tentei, em um .d.ts :

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

Isso não funciona, porém, recebo "Não é possível localizar o nome 'React'". Existe outra maneira de exportar todo o módulo como global, sem modificar o react.d.ts subjacente?

Question

Comentários muito úteis

Olá @Evertt , estou recebendo este erro agora também. Inicialmente, meu código-fonte não estava usando a sintaxe do módulo ES6, mas depois que refatorei alguns arquivos para essa sintaxe, recebi o mesmo erro. Fiz algumas pesquisas e o que funcionou para mim agora é quando eu crio o segundo arquivo globals.d.ts e o coloco também na pasta de digitação:

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

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

Na verdade, esse arquivo sozinho parece "satisfazer" o compilador de texto digitado, portanto, em teoria, você não precisaria dos outros arquivos que mencionei anteriormente. No entanto, em meu caso particular (estou usando WebStorm), quando tinha apenas o arquivo globals.d.ts, meu IDE estava constantemente me pingando para importar os módulos e também as conclusões nesses globais estavam incompletas. Então, basicamente mantive agora ambos os arquivos no diretório de digitação que satisfaz o typescript e meu IDE. Não é muito bom, mas para os poucos globais que normalmente se usa, acho que não há problema em manter esses arquivos.

Este é o meu tsconfig.json para referência:

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

Não estou usando webpack ou qualquer coisa para agrupar. Acabei de transpilar os arquivos individuais e carregá-los por meio do sistema de módulos https://github.com/SAP/openui5 (que é semelhante ao AMD) e agrupá-los apenas para produção.

A versão datilografada é: 2.2.1

Espero que ajude.

Todos 11 comentários

Não é possível fazer isso porque no minuto em que você adiciona uma declaração import a um arquivo de origem, ela é considerada um módulo externo. Alguma razão de você não estar usando o arquivo de definição React que usa um global?

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

Parece-me que isso resolveria o problema.

Na verdade, eu tentei react-global.d.ts também, o que obviamente coloca React no espaço global, mas como poderia renomeá-lo globalmente e deixar o Typescript saber sobre isso?

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

Meu caso de uso real seria ser capaz de içar um módulo de tipo utilitário / comum para o espaço global, de modo que não precise usar um monte de importações de caminho relativo para chegar até ele. Posso fazer isso em Javascript, mas estou tendo dificuldades para informar ao compilador do Typescript que fiz isso.

@ahejlsberg - Tenho certeza que você tem muito mais coisas importantes a fazer do que

Você poderia, por exemplo, criar um arquivo de declaração r.d.ts :

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

e então apenas faça referência a esse arquivo em qualquer lugar. Ou melhor ainda:

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

o que permitirá que você também faça referência a tipos do React como R.xxx.

Nunca vi um uso de typeof antes - muito legal. Isso funciona muito bem para os módulos já definidos de um .d.ts , mas ainda não vejo uma maneira de içar um módulo externo definido em Typescript para o espaço global e fazer com que o Typescript saiba disso. Talvez porque seja um anti-padrão e eu deveria apenas superar isso ...

Recebemos alguns pedidos (por exemplo, # 2357) para estender typeof para oferecer suporte a módulos externos, mas até agora não houve muita demanda para o recurso.

De modo geral, os programas são escritos sem módulos externos ou exclusivamente com módulos externos. Além da parte de bootstrap de um aplicativo de navegador AMD, realmente não há ambiente de execução onde o modelo misto seja possível. Então, sim, é principalmente um antipadrão.

Obrigado por dedicar todo o seu tempo para me agradar sobre isso! Acabei de começar a explorar módulos externos (para brincar com os próximos frameworks Angular2 e Aurelia). Problemas como nº 17, nº 2338 e nº 2839 parecem ser mais o que estou procurando no final. Espero ter um feedback mais claro à medida que me aprofunde em meu projeto atual.

Ainda não é possível fazer? Estou tentando usar o TypeScript com VueJS e gostaria muito se pudesse importar algumas coisas para o namespace global para que todos os componentes possam usá-lo sem ter que importar essas coisas. Houve algum progresso ou hacks para fazer isso funcionar?

@Evertt

Eu encontrei uma maneira que aparentemente funciona com o typescript 2.xx. No meu caso, eu quero expor a biblioteca ramda como global R .

  1. npm install ramda @types/ramda
  2. criar arquivo typings/ramda.d.ts
  3. adicione a pasta typings recém-criada aos includes em .tsconfig.json:
"include": [
    "typings/**/*",
     ...
]
  1. adicione a magia a typings/ramda.d.ts :
import * as _R from 'ramda';

export as namespace R;
export = _R; 

Agora, todos os arquivos ts em meu projeto assumem que existe um R global digitado sem que eu faça mais nenhuma importação ou qualquer outra coisa nesses arquivos.

@geekflyer quando tento fazer isso usando o seguinte código em meu types/vue.d.ts :

import * as V from 'vue'

export as namespace Vue
export = V

Eu recebo o seguinte erro sempre que tento usar aquele Vue global em algum lugar:

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

Você também obteve esse erro em algum momento? Se sim, o que você fez a respeito?

editar

Se você não obtiver esse erro e não tiver certeza do motivo pelo qual recebo esse erro, estaria disposto a me mostrar todo o seu tsconfig.json e talvez até mesmo a configuração do webpack?

Olá @Evertt , estou recebendo este erro agora também. Inicialmente, meu código-fonte não estava usando a sintaxe do módulo ES6, mas depois que refatorei alguns arquivos para essa sintaxe, recebi o mesmo erro. Fiz algumas pesquisas e o que funcionou para mim agora é quando eu crio o segundo arquivo globals.d.ts e o coloco também na pasta de digitação:

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

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

Na verdade, esse arquivo sozinho parece "satisfazer" o compilador de texto digitado, portanto, em teoria, você não precisaria dos outros arquivos que mencionei anteriormente. No entanto, em meu caso particular (estou usando WebStorm), quando tinha apenas o arquivo globals.d.ts, meu IDE estava constantemente me pingando para importar os módulos e também as conclusões nesses globais estavam incompletas. Então, basicamente mantive agora ambos os arquivos no diretório de digitação que satisfaz o typescript e meu IDE. Não é muito bom, mas para os poucos globais que normalmente se usa, acho que não há problema em manter esses arquivos.

Este é o meu tsconfig.json para referência:

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

Não estou usando webpack ou qualquer coisa para agrupar. Acabei de transpilar os arquivos individuais e carregá-los por meio do sistema de módulos https://github.com/SAP/openui5 (que é semelhante ao AMD) e agrupá-los apenas para produção.

A versão datilografada é: 2.2.1

Espero que ajude.

@geekflyer obrigado, isso foi muito útil

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

Questões relacionadas

bgrieder picture bgrieder  ·  3Comentários

manekinekko picture manekinekko  ·  3Comentários

weswigham picture weswigham  ·  3Comentários

seanzer picture seanzer  ·  3Comentários

uber5001 picture uber5001  ·  3Comentários