Typescript: Ermöglichen, dass Moduldefinitionen als globale Variablen deklariert werden

Erstellt am 15. Mai 2015  ·  11Kommentare  ·  Quelle: microsoft/TypeScript

Ich habe die React-Typdefinitionsdatei (die mit einem externen Modul deklariert wird). In meinen Quelldateien mache ich normalerweise:

import * as R from "react"

und kann dann glücklich R.createElement(... usw. in einer stark typisierten Weise verwenden. Ich kann sogar:

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

Ich möchte, dass R nicht in jede Datei importiert werden muss, sondern als globale Deklaration (ja, ich bin bereit, den globalen Namespace mit einigen Variablen zu verschmutzen). Ich habe versucht, in einem .d.ts :

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

Dies funktioniert jedoch nicht. Ich erhalte die Meldung "Name 'Reagieren' kann nicht gefunden werden". Gibt es eine andere Möglichkeit, das gesamte Modul als global zu exportieren, ohne die untergeordnete Reaktion.d.ts ändern zu müssen?

Question

Hilfreichster Kommentar

Hi @Evertt in der Tat, ich bekomme diesen Fehler jetzt auch. Ursprünglich verwendete mein Quellcode keine ES6-Modulsyntax, aber nachdem ich einige Dateien auf diese Syntax umgestaltet hatte, wurde der gleiche Fehler angezeigt. Habe einige Nachforschungen angestellt und was jetzt für mich funktioniert hat, ist, wenn ich die zweite Datei globals.d.ts erstelle und sie auch in den Eingabeordner lege:

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

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

Tatsächlich scheint diese Datei allein den Typoskript-Compiler zu "befriedigen", so dass Sie theoretisch die anderen Dateien, die ich zuvor erwähnt habe, nicht benötigen würden. In meinem speziellen Fall (ich verwende WebStorm), in dem nur die Datei globals.d.ts vorhanden war, hat mich meine IDE ständig zum Importieren der Module aufgefordert, und auch die Vervollständigungen dieser Globals waren unvollständig. Also habe ich jetzt im Grunde beide Dateien im Schreibverzeichnis aufbewahrt, das Typoskript und meine IDE erfüllt. Nicht wirklich schön, aber für die wenigen Globals, die man normalerweise verwendet, ist es in Ordnung, diese Dateien zu pflegen.

Dies ist mein tsconfig.json für die Verteidigung:

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

Ich verwende kein Webpack oder irgendetwas zum Bündeln. Ich transpiliere einfach die einzelnen Dateien und lade sie über das Modulsystem https://github.com/SAP/openui5 (ähnlich wie AMD) und bündle sie nur für die Produktion.

Typoskript-Version ist: 2.2.1

Hoffentlich hilft das.

Alle 11 Kommentare

Dies ist nicht möglich, da in dem Moment, in dem Sie einer Quelldatei eine import -Deklaration hinzufügen, diese als externes Modul betrachtet wird. Gibt es einen Grund, warum Sie die React-Definitionsdatei nicht verwenden, die eine globale Datei verwendet?

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

Sieht für mich so aus, als würde dies das Problem lösen.

Ich habe tatsächlich auch react-global.d.ts ausprobiert, wodurch React offensichtlich in den globalen Bereich gestellt wird. Aber wie würde ich es global umbenennen und Typescript darüber informieren?

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

Mein eigentlicher Anwendungsfall wäre es, ein Dienstprogramm- / Common-Type-Modul in den globalen Bereich zu heben, damit ich nicht eine Reihe relativer Pfadimporte verwenden muss, um dorthin zu gelangen. Ich kann dies in Javascript tun, habe aber Probleme damit, wie ich den Typescript-Compiler wissen lasse, dass ich es getan habe.

@ahejlsberg - Ich bin sicher, Sie haben viel mehr Überlegungen zu Randfällen abzufinden ... :)

Sie können beispielsweise eine Deklarationsdatei r.d.ts erstellen:

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

und dann einfach überall auf diese Datei verweisen. Oder noch besser:

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

Damit können Sie auch Typen aus React als R.xxx referenzieren.

Ich habe noch nie eine Verwendung von typeof - ziemlich cool. Dies funktioniert hervorragend für bereits definierte Module ab einem .d.ts , aber ich sehe immer noch keine Möglichkeit, ein in Typescript definiertes externes Modul in den globalen Bereich zu heben und Typescript darüber zu informieren. Vielleicht, weil es ein Anti-Muster ist und ich einfach darüber hinwegkommen sollte ...

Wir hatten einige Anfragen (z. B. # 2357), typeof zu erweitern, um externe Module zu unterstützen, aber bisher gab es keine große Nachfrage nach dieser Funktion.

Im Allgemeinen werden Programme entweder ohne externe Module oder ausschließlich mit externen Modulen geschrieben. Außer dem Bootstrap-Teil einer AMD-Browser-App gibt es wirklich keine Ausführungsumgebung, in der das gemischte Modell überhaupt möglich ist. Also ja, es ist meistens ein Anti-Muster.

Vielen Dank, dass Sie sich die Zeit genommen haben, mich darüber zu unterhalten! Ich habe gerade angefangen, externe Module zu untersuchen (um mit den kommenden Angular2- und Aurelia-Frameworks zu spielen). Themen wie # 17, # 2338 und # 2839 scheinen am Ende eher das zu sein, wonach ich suche. Hoffentlich bekomme ich ein klareres Feedback, wenn ich tiefer in mein aktuelles Projekt eintauche.

Ist das noch nicht möglich? Ich versuche, TypeScript mit VueJS zu verwenden, und ich würde mich sehr freuen, wenn ich ein paar Dinge in den globalen Namespace importieren könnte, damit alle Komponenten es verwenden können, ohne diese Dinge importieren zu müssen. Wurden Fortschritte oder Hacks erzielt, damit dies funktioniert?

@Evertt

Ich habe einen Weg gefunden, der anscheinend mit Typoskript 2.xx funktioniert. In meinem Fall möchte ich die Bibliothek ramda als globales R verfügbar machen.

  1. npm install ramda @types/ramda
  2. Datei erstellen typings/ramda.d.ts
  3. Fügen Sie den neu erstellten Ordner typings zu den Includes in .tsconfig.json hinzu:
"include": [
    "typings/**/*",
     ...
]
  1. füge die Magie zu typings/ramda.d.ts :
import * as _R from 'ramda';

export as namespace R;
export = _R; 

Jetzt setzen alle ts-Dateien in meinem Projekt ein typisiertes globales R voraus, ohne dass ich weitere Importe oder was auch immer in diesen Dateien vornehme.

@geekflyer, wenn ich versuche, dies mit dem folgenden Code in meinem types/vue.d.ts zu tun:

import * as V from 'vue'

export as namespace Vue
export = V

Ich erhalte die folgende Fehlermeldung, wenn ich versuche, dieses globale Vue irgendwo zu verwenden:

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

Hast du diesen Fehler auch irgendwann bekommen? Wenn ja, was haben Sie dagegen getan?

bearbeiten

Wenn Sie diesen Fehler nicht erhalten und nicht sicher sind, warum ich diesen Fehler erhalte, sind Sie möglicherweise bereit, mir Ihre gesamte tsconfig.json und möglicherweise sogar Ihre Webpack-Konfiguration anzuzeigen?

Hi @Evertt in der Tat, ich bekomme diesen Fehler jetzt auch. Ursprünglich verwendete mein Quellcode keine ES6-Modulsyntax, aber nachdem ich einige Dateien auf diese Syntax umgestaltet hatte, wurde der gleiche Fehler angezeigt. Habe einige Nachforschungen angestellt und was jetzt für mich funktioniert hat, ist, wenn ich die zweite Datei globals.d.ts erstelle und sie auch in den Eingabeordner lege:

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

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

Tatsächlich scheint diese Datei allein den Typoskript-Compiler zu "befriedigen", so dass Sie theoretisch die anderen Dateien, die ich zuvor erwähnt habe, nicht benötigen würden. In meinem speziellen Fall (ich verwende WebStorm), in dem nur die Datei globals.d.ts vorhanden war, hat mich meine IDE ständig zum Importieren der Module aufgefordert, und auch die Vervollständigungen dieser Globals waren unvollständig. Also habe ich jetzt im Grunde beide Dateien im Schreibverzeichnis aufbewahrt, das Typoskript und meine IDE erfüllt. Nicht wirklich schön, aber für die wenigen Globals, die man normalerweise verwendet, ist es in Ordnung, diese Dateien zu pflegen.

Dies ist mein tsconfig.json für die Verteidigung:

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

Ich verwende kein Webpack oder irgendetwas zum Bündeln. Ich transpiliere einfach die einzelnen Dateien und lade sie über das Modulsystem https://github.com/SAP/openui5 (ähnlich wie AMD) und bündle sie nur für die Produktion.

Typoskript-Version ist: 2.2.1

Hoffentlich hilft das.

@geekflyer danke das war sehr hilfreich

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen