Typescript: Unterstützung der Suche nach Modulen unter node_modules beim Importieren

Erstellt am 25. Juli 2014  ·  138Kommentare  ·  Quelle: microsoft/TypeScript

Aktualisierung 5. November 2015

Die unten angeforderte Funktionalität ist derzeit seit mindestens 1.8 in Typoskript implementiert, mit einem Hauptunterschied:

Anstelle der typescript.main - und typescript.definition -Eigenschaften gibt es nur eine typings -Eigenschaft, die Sie entweder auf eine d.ts -Datei oder eine normale .ts -Datei verweisen können

Wenn Sie ein Modul entwickeln, das nur lokal verwendet werden soll, können Sie typings auf eine .ts -Datei verweisen lassen, aber wenn Sie vorhaben, das Modul zu veröffentlichen, wird empfohlen, es darauf verweisen zu lassen eine d.ts -Datei. Dies liegt daran, dass Ihre Modulkonsumenten Ihre Moduldateien nicht neu kompilieren sollen, sondern nur ihre Typisierungen konsumieren.

Ich habe ein Beispiel für die Verwendung dieses hier eingerichtet:
https://github.com/chanon/typescript_module_example

Hier gibt es eine Dokumentationsseite mit weiteren Informationen:
http://www.typescriptlang.org/docs/handbook/typings-for-npm-packages.html

Vielen Dank an die TypeScript-Entwickler und alle Mitwirkenden.

Ursprüngliches Problem / Funktionsanfrage folgt


Motivation

In TypeScript ist es viel schwieriger, TypeScript-Module wiederzuverwenden als npm-Module in JavaScript wiederzuverwenden.

Es wäre von Vorteil, wenn der Typescript-Compiler intelligent genug wäre, um in node_modules-Ordnern und package.json-Dateien zu suchen.

Der Grund dafür ist, dass npm-Modulentwickler, die TypeScript verwenden, möglicherweise mit dem Schreiben und Verteilen von Modulen über npm selbst beginnen können. TypeScript wäre in der Lage, auf die Infrastruktur und die breite Unterstützung von npm zurückzugreifen.

Beispiel für node_modules

Wenn wir hätten:

./node_modules/concator/index.ts
./myApp.ts

Und in index.ts hatten wir:

export function concat(param1: string, param2:string): string {
      return param1 + ' ' + param2;
}

in myApp.ts:

import concator = require('concator');  // loads the module from node_modules
var result = concator.concat('I like', 'this.');
var wontWork = concator.concat('this will fail');  // compile error, concat needs 2 params

Im Grunde genommen ist der Compiler intelligent genug, um das Modul in node_modules zu finden, und verwendet automatisch die Typoskript-Version (index.ts).

Wenn der Code dann in JavaScript kompiliert wird, verwendet er natürlich die JavaScript-Version.

Importieren von Ordnern als Module

Ein einfacherer Fall ist die Unterstützung der beliebten Node.js-Regel von http://nodejs.org/api/modules.html#modules_folders_as_modules , wie von @vvakame unten und in der geschlossenen (halbduplizierten) Ausgabe Nr. 207 vorgeschlagen.

typescript.main in package.json

Es könnte einen Zusatz zu den package.json-Dateien geben, um anzugeben, wo sich die Haupt-.ts-Datei eines TypeScript-npm-Moduls befindet. Dies wäre ähnlich dem Schlüssel main , der angibt, wo sich die Haupt-JavaScript-/.js-Datei befindet, aber stattdessen für TypeScript.

Beispiel: package.json für ein npm-Modul mit dem Namen „myModule“, das sich unter node_modules/myModule/package.json befindet

{
     "main": "./dist/index.js",
     "typescript": {
          "main": "./src/index.ts"
     }
}

In diesem Beispiel wäre node_modules/myModule/src/index.ts die TypeScript-Hauptdatei und import myModule = require("myModule"); würde die Datei node_modules/myModule/src/index.ts importieren.

Für einen JavaScript-Programmierer, der var myModule = require("myModule"); in eine JavaScript-Datei schreibt, würde das require die Datei node_modules/myModule/dist/index.js wie gewohnt laden.

Wie in diesem Beispiel zu sehen ist, befindet sich die TypeScript-Quelle im Ordner node_modules/module-name/src und die kompilierten JS-Dateien befinden sich in node_modules/module-name/dist .

So etwas könnte ein (Halb-)Standard für TypeScript-npm-Module sein, damit die TypeScript-Quelle sauber von der kompilierten JavaScript-Ausgabe getrennt wird.

Ein einfacherer Fall, wie von @vvakame unten vorgeschlagen, ist die Unterstützung der beliebten Node.js-Regel von http://nodejs.org/api/modules.html#modules_folders_as_module

typescript.definition in package.json

Ein weiterer möglicher Schlüssel für package.json für Nicht-TypeScript-npm-Module (einfaches JavaScript) könnte typescript.definition sein. Dies würde auf eine .d.ts-Datei verweisen, die das Modul für TypeScript-Benutzer des npm-Moduls definiert.

Also das ein
import $ = require('jquery');
würde automatisch eine jquery.d.ts -Datei lesen, die im typescript.definition -Schlüssel in jQuerys package.json definiert ist, und $ zum richtigen Typ machen.

Beispielformat:

{
     "main": "./dist/index.js",
     "typescript": {
          "definition": "./index.d.ts"
     }
}

(Dieses Format wird bereits von tsd verwendet, wie @Bartvds unten erklärt.)

Dann müssten wir TypeScript-Programmierer nur versuchen, möglichst viele Nicht-TypeScript-npm-Modulbetreuer dazu zu bringen, unsere Pull-Requests zusammenzuführen, die unsere .d.ts-Dateien und package.json typescript.definition -Schlüssel enthalten.

Wenn uns das gelingt, dann wäre das Leben von TypeScript-Programmierern ein Glücksfall ... keine separate Verwaltung von DefinitelyTyped .d.ts-Dateien mehr. Installieren Sie einfach npm und Sie erhalten auch Ihre TypeScript-Definitionen! Automatisch und aktuell mit der installierten Modulversion.

Liste der Vorteile

Was wir von all dem bekommen, ist

  • npm-Module können in TypeScript geschrieben werden.
  • Sowohl TypeScript- als auch JavaScript-Programmierer können diese Module verwenden
  • Die Modulbenutzer, die TypeScript verwenden, profitieren von den Vorteilen der statischen Typisierung, ohne dass der Modulcodierer (oder Benutzer) die übliche Methode zum Schreiben (oder Generieren) separater .d.ts-Dateien verwenden muss (wenn sich der Quellcode des Moduls also bereits in TypeScript befindet wir müssen keine weitere .d.ts-Datei pflegen)
  • Es gäbe eine Möglichkeit, TypeScript-Module mit npm, mit dem jeder bereits vertraut ist, einfach wiederzuverwenden und zu verteilen
  • Es könnte helfen, die TypeScript-Nutzung selbst zu fördern, da JavaScript-Programmierer, die die in TypeScript geschriebenen npm-Module verwenden, möglicherweise sehen, wie schön / besser die TypeScript-Quelle ist, und versuchen, zu ihr zu wechseln. Oder sie möchten vielleicht etwas zu dem Modul beitragen, und da die Quelle in TypeScript ist, müssten sie es lernen, was dazu führen könnte, dass es ihnen gefällt und sie sich entscheiden, es in ihren eigenen Projekten zu verwenden.
  • Im Grunde würde es helfen, die TypeScript-Community durch all das Code-Sharing, das sich daraus ergeben könnte, zu vergrößern. Im Moment ist der TypeScript-Code aller meistens sein eigener / in seinem eigenen Silo. Dies ist wahrscheinlich eine äußerst wichtige Sache, da das Fehlen einer geeigneten/einfachen Möglichkeit zum Teilen/Verteilen/Wiederverwenden von Modulen wahrscheinlich das Wachstum der Sprache einschränkt. [1]
  • Die Wiederverwendung von Modulen in internen Projekten wäre viel weniger umständlich und würde die Notwendigkeit all dieser relativen Pfade zu .d.ts-Dateien und relativen Pfaden in Modulanforderungen und allgemeinem .d.ts-Zeug reduzieren. (Im Moment muss ich beim Schreiben von TypeScript-Code lernen, gut mit dem Zählen von ../../ s umzugehen.)
  • Dieser Ansatz unterstützt auch Browserify/Webpack, da Browserify/Webpack auch unter node_modules nachsehen, sodass dies einfache wiederverwendbare/npm-verteilte TypeScript-Module sowohl für den Server als auch für den Browser ermöglicht
  • Nicht-TypeScript-npm-Module können problemlos in TypeScript mit Typinformationen durch den Schlüsselzusatz typescript.definition verwendet werden. Dadurch können .d.ts-Definitionsdateien zusammen mit dem npm-Modul gepackt werden, sodass beim Aktualisieren eines npm-Moduls automatisch dessen .d.ts-Definitionsdatei aktualisiert wird. Dadurch entfällt die Notwendigkeit, .d.ts-Dateien manuell zu aktualisieren.
  • Die Verwendung von Definitionsdateien über typescript.definition ist einfacher, da es sich einfach um eine import moduleName = require("moduleName") -Anweisung handelt, ohne dass eine separate ///<reference ... erforderlich ist
  • Die Verwendung von Definitionsdateien über die typescript.definition sollte auch die Verwendung verschiedener Versionen des Moduls in derselben Codebasis ermöglichen, ohne dass sich Typnamen überschneiden.

Detailliertes Angebot

@Nemo157 hat einen sehr detaillierten Vorschlag geschrieben, wie das alles funktionieren soll:

Vorgeschlagene TypeScript-Require-Resolution-Semantik
https://gist.github.com/Nemo157/f20064a282ee620f3877

Eine Ergänzung im Vorschlag ist die Verwendung von /typings -Ordnern, die Definitionsdateien enthalten können, die automatisch von Tools wie tsd für JavaScript-npm-Module verwaltet werden können, die keine Definitionsdateien in ihren Repositories enthalten .

Abschließende unterstützende Fakten

Da TypeScript zu JavaScript kompiliert wird, das hauptsächlich an zwei Stellen ausgeführt wird: node.js und in Browsern, ist die Unterstützung von node_modules aufgrund von npm und Browserify/Webpack für beide Stellen (praktisch überall dort, wo TypeScript verwendet wird) von Vorteil.

dh. Es gibt keinen Grund, sich ein anderes Schema auszudenken, wenn node_modules das ist, was alle TypeScript-Benutzer bereits für vielleicht 75 % bis 100 % ihres gesamten JavaScript-Codes verwenden. (25 % für vielleicht RequireJS-Benutzer herausnehmen.)

Fußnoten

[1] - Übrigens sehe ich, dass es einen NuGet-Paketmanager (?) von Microsoft gibt, der Typoskript-Module (?) verteilen kann, aber da er aus einem node.js-fokussierten (nicht .NET-fokussierten) Hintergrund kommt, sehe ich nicht, dass NuGet wird außerhalb von Microsoft-orientierten Shops weit verbreitet, insbesondere da npm _der_ Standard für node.js und auch ein führender Standard für clientseitiges JavaScript ist. Wenn ich TypeScript nicht verwendet hätte, hätte ich nie von NuGet gehört. Der durchschnittliche node.js-/clientseitige JavaScript-Codierer würde es wahrscheinlich vorziehen, npm zu verwenden, das gleiche Tool, das er bereits verwendet, anstatt etwas Microsoft-spezifisches wie NuGet verwenden zu müssen. (Ich weiß eigentlich nichts über NuGet, also spielt es vielleicht keine Rolle, was ich hier sage.)

Committed Suggestion

Hilfreichster Kommentar

Jedenfalls behauptet der Compiler derzeit, dass er das Modul nicht finden kann, obwohl er sich in Wirklichkeit nur weigert, das Modul ohne Typdefinition zu importieren. Das ist nicht wirklich hilfreich, oder?

Alle 138 Kommentare

[in der obigen Problembeschreibung nach typescript.main in package.json verschoben ]

:+1:
Ich denke, http://nodejs.org/api/modules.html#modules_folders_as_modules ist eine sehr beliebte Regel von Node.js.

anderes Beispiel.

./test/index.ts

export function hello() { return "Hello, world"; }

./main.ts

import test = require("./test/");
console.log(test.hello()); // print "Hello, world"

[in der obigen Problembeschreibung nach typescript.definition in package.json verschoben ]

Eine Lösung wäre, es mit besseren Werkzeugen zu lösen. Beispiel: import foo = require('foo') gibt Ihnen einen Hinweis, nach einer lokalen node_module+package.json (foo ist ein ts-Projekt) oder einer DT-Definition (foo ist ein js-Projekt, bei dem Bibliotheksautoren die ts def nicht pflegen möchten) zu suchen. .

Zu Ihrer Information; Ich teste gerade etwas Ähnliches in TSD; eine Möglichkeit, Definitionen bereitzustellen und zu verknüpfen, die in den npm- (oder bower-) Paketen gebündelt sind.

Es ist in meiner Dev-Version für 0.6 und funktioniert durch Hinzufügen eines typescript -Elements zu package.json (oder bower.json) mit einem Unterelement definition (ein Unterelement, weil vielleicht eines Tag gäbe es auch source oder was auch immer).

{
    ...
    "main": "./index.js",
    "typescript": {
        "definition": "./foo.d.ts"
    }
    ...
},

Dann können Sie einen Befehl auf TSD ausführen, derzeit tsd link , und es wird alle package.json-Dateien in node_modules (oder bower oder was auch immer) scannen, diese Eigenschaft finden, falls definiert, und einen Verweis darauf zum zentralen tsd.d.ts hinzufügen

Beispiel: hier definiert und hier verwenden

@Bartvds Das ist ziemlich nett. Könnte der erste Schritt sein, um .d.ts in npm-Paketen zu haben. Ich mag die package.json-Struktur mit „definition“ in „typescript“, sie ist viel besser organisiert.

Wenn der TypeScript-Compiler es automatisch lesen könnte, wäre das sehr cool.

Markieren Sie dies zur Diskussion – intelligentere externe Modulauflösung ist etwas, worüber wir sprechen müssen, um die verschiedenen Szenarien hier zu verstehen. Dies wurde zuvor angesprochen und wir haben in 1.0 einige Änderungen vorgenommen.

Besprechen Sie auch #207 - Suchen Sie unter "Index".

:+1:

@chanon tsMain ist nicht erforderlich, wenn wir die Deklarationsgenerierung verwenden.

Ja, das Thema ist auch für Browser immens wichtig - viele Projekte verwenden browserify/packify und damit Node-kompatible Verzeichnislayouts

:+1:

Es gab bereits einige Arbeit in diesem Bereich im Codeplex-Repo, eine Pull-Anforderung von leebyron und eine von kayahr .

Ich wollte versuchen, einen davon in das neue Repository zu portieren, aber es scheint, dass der zugehörige Code stark neu arrangiert wurde.

Ich habe einen Vorschlag geschrieben, wie dies dem TypeScript-Compiler hinzugefügt werden kann . Dazu gehört auch das Durchsuchen des typings -Verzeichnisses, da dies wichtig ist, wenn Sie mit Javascript-Modulen arbeiten, die keine eigenen Typoskript-Definitionen verwalten. Leider wird es noch ein wenig Arbeit erfordern, dies alles mit tsd transparent zu machen, da die Anforderung, dass /// <reference d-Dateien externe Umgebungsdeklarationen sein müssen, die Dinge ein wenig haarig macht. Ich werde einen Blick darauf werfen, wie dies in einem Zweig implementiert wird, und einige Beispielmodule bereitstellen, die es verwenden.

Sieht vernünftig aus. Wird dies Module mit widersprüchlichen Typabhängigkeiten abdecken? Ich meine, wenn eine App A und B importiert und B auch von A abhängig ist. Es ist leicht, in doppelte Typfehler zu verfallen, wenn es zwei Kopien der externen Deklarationen gibt.

Es sollte nicht, sie sollten in verschiedene externe Modulnamen aufgelöst werden, also deklarieren Sie identisch benannte unabhängige Typen in verschiedenen Modulen. Die strukturelle Typprüfung sollte dann ein reibungsloses Zusammenspiel der verschiedenen Module ermöglichen.

Das ist eines der Hauptprobleme mit den aktuellen tsd -Definitionen, die dies zu lösen versucht. Durch die Definition externer Ambient-Module gibt es für sie keine Möglichkeit, mit mehreren Versionen einer Bibliothek mit identischem Namen, aber leicht unterschiedlichen Typen umzugehen .

@joewood auch es wird Probleme zwischen verschiedenen Versionen von A geben

├── [email protected]
└── [email protected]
    └── [email protected]

Es gibt keine Möglichkeit für sie, mit mehreren Versionen einer Bibliothek mit identisch benannten, aber leicht unterschiedlichen Typen umzugehen.

daran interessiert, Lösungen für dasselbe zu hören. TypeScript hat einen Variablenbereich auf Ebene global für Ambient-Deklarationen

Selbst wenn die Versionen übereinstimmen, sehe ich im Moment Probleme mit zwei verschiedenen, aber übereinstimmenden Ambient-Deklarationsdateien, die zu doppelten Symbolfehlern führen. Die lokal definierte Direktive /// reference muss irgendwie wieder in eine einzelne Datei aufgelöst werden. Entweder das, oder die Typidentität muss den Pfad enthalten, und die strukturelle Typisierung kümmert sich um Versionskonflikte usw.

@joewood Ja , ich hoffe, das wird in den meisten Fällen behoben, indem require geändert wird, um die richtigen Definitionen zu laden, wobei /// reference nach Möglichkeit vermieden wird. Die externen Module werden durch ihre absoluten Pfade identifiziert, anstatt Ambient-Deklarationen zu haben, daher sollte das Laden mehrerer gleicher Namen aus verschiedenen Pfaden und in verschiedenen Versionen möglich sein.

Ja, ich hoffe, das wird in den meisten Fällen behoben, indem Sie require ändern, um die richtigen Definitionen zu laden, und ///-Referenzen wo immer möglich vermeiden.

:+1:

:+1: Danke @Nemo157 und allen für die Diskussion.

Ich habe den Text der obersten Ausgabe aktualisiert, um die Ergänzungen von package.json zusammenzuführen und mit dem Vorschlag von @Nemo157 verknüpft.

:+1:

Ich habe eine erste Implementierung meines Vorschlags durchgeführt und einen Beispielsatz von Modulen erstellt, um zu zeigen, dass alle verschiedenen Möglichkeiten zum Erstellen eines Moduls funktionieren. Einschließlich der Verwendung verschiedener Versionen derselben Bibliothek in verschiedenen Untermodulen.

:+1:

Ordner als Module mit index.ts :+1:

:+1:

:+1:

:+1:

:+1:

:+1: :+1: :+1:

:+1: :+1: :+1: :+1:

Kommentieren, um dies wieder auf unser Radar zu stoßen.

Ich hatte guten Erfolg mit dem Vorschlag von @ Bartvds :

Dann können Sie einen Befehl auf TSD ausführen, derzeit tsd link, und er scannt alle package.json-Dateien in node_modules (oder bower oder was auch immer), findet diese Eigenschaft, falls definiert, und fügt dem zentralen tsd.d.ts-Bundle einen Verweis darauf hinzu in Ihrem Projekt.

Erwägen Sie also auf jeden Fall, typescript in package.json zu unterstützen, da dies der Weg der Community ist.

Wir müssen tsc auf jeden Fall den Ordner node_modules kennen, wenn TypeScript in der node.js-Community weit verbreitet sein soll. Ich verwende derzeit Symlinks zu Modulen, die Teil meines Entwicklungsprojekts sind (unter Verwendung von npm-workspace), und ich habe im Moment zwei Möglichkeiten:

  • direkt aus node_modules importieren, was falsch aussieht: import Foo = require("node_modules/mymodule/Foo");
  • Lassen Sie tsc die Deklarationsdateien generieren und fügen Sie sie dann zusammen, indem Sie eine manuell gepflegte Moduldeklarationsdatei verwenden, die die String-Modulnamen umschaltet

Könnte tsc den externen Modulnamen in Importdeklarationen überprüfen und dann während der Pfadauflösung auch node_modules auf die gleiche Weise anwenden, wie es die node.js-Laufzeit tut? Eine Compileroption könnte dies auch ein- oder ausschalten.

:+1: :+1: :+1:

Könnte tsc den externen Modulnamen in Importdeklarationen überprüfen und dann während der Pfadauflösung auch node_modules auf die gleiche Weise anwenden, wie es die node.js-Laufzeit tut

So _sollte_ es sein. Die derzeitige Art, einfach im Verzeichnisbaum nach einer Datei mit dem genannten Namen zu suchen, hat keine Ähnlichkeit mit JS-Ausführungskontexten.

Das steht schon länger auf meiner Liste. werde versuchen, dies in der nächsten Version zu erhalten.

Wir ( Booktrack ) verwenden TypeScript für unsere gesamte Webentwicklung und stehen vor ähnlichen Herausforderungen wie die node.js-Entwickler. Ich melde mich zu Wort, weil die Stimme der Web-Entwickler nicht so laut zu sein scheint wie die der Node-Entwickler.

Lösungen (in der Reihenfolge vom schlechtesten zum besten für uns):

  1. Auflösung von externen Modulnamen der obersten Ebene über fest codiertes Nachschlagen in node_modules
  2. keine Kontrolle über die Auflösung von externen Modulnamen der obersten Ebene
  3. ein Compiler-Flag, um die optionale Auflösung von externen Modulnamen der obersten Ebene in das node_modules -Verzeichnis zu steuern
  4. ein Compiler-Parameter "Modul-Suchpfad(e)", um die optionale Auflösung von externen Modulnamen der obersten Ebene in die angegebenen Pfade zu steuern
  5. ein Compiler-„Modul-Resolver“-Parameter, um dem Compiler ein JS-Plugin bereitzustellen, das alle (nicht nur die obersten) externen Modulnamen auflöst
  6. geeignete Hooks in Sprachdienste, so dass die Namensauflösung externer Module steuerbar ist

Option 1 ist schrecklich, ich bevorzuge Option 2.

Option 5 und 6 würden exotische Verwendungen von import-Anweisungen ermöglichen, wie sie beispielsweise bei der Arbeit mit requirejs oder Webpack-Plugins zu finden sind. Die Grundidee: Der Compiler delegiert alle externen Modulnamen-Lookups (nicht nur auf oberster Ebene) an einen Drittanbieter (ein Plugin oder Callback). Der Delegat, der den Pfad zum zu kompilierenden Modul und den Namen des externen Moduls erhält, gibt den Dateisystempfad ODER die Typinformationen für den angegebenen Modulnamen an den Compiler zurück.

Ich wäre glücklich, wenn Option 4 implementiert würde, erfreut, wenn Option 6 implementiert würde, und überglücklich, wenn sowohl Option 4 als auch Option 6 implementiert würden.

Wie wäre es mit einem --basePath für Ihr Modulsuchverzeichnis, alle Modulimporte werden relativ zu diesem Pfad gesucht. Dies gilt nur für AMD.

Ich denke, das Knotenproblem ist viel einfacher, wir müssen es nur implementieren :)

Beachten Sie, dass wir hier vor langer Zeit tatsächlich eine Implementierung (und Tests) von @Nemo157 erhalten haben https://github.com/Microsoft/TypeScript/issues/247#issuecomment -57422329

Stimmen Sie @mark-buer und @mhegazy zu , Option 4, ein Suchpfad, sollte eine einfache Lösung sein. Eine aufwändigere Lösung im Sprachendienst (Option 6) ist auf jeden Fall längerfristig erforderlich.

_Hinzufügenswert_: Dies allein wird das TypeScript-Wiederverwendungsproblem in npm aufgrund des Problems mit doppelten Symbolen für allgemeine Typreferenzen # 1125 nicht beheben. Wir müssen wirklich vermeiden ///indem Sie .tsconfig- Dateien verwenden und dies ordnungsgemäß beheben, indem Sie Pakete in einem einzigen externen typisierten Modul bündeln, wie in #17 vorgeschlagen

Eine weitere Stimme dafür, dass der Ordner node_modules vom Typoskript-Compiler erkannt wird.

Für CommonJS-Module sollte Typescript idealerweise der gleichen Dateinamenauflösung folgen wie require.resolve (wie im Pseudocode auf dieser Seite beschrieben: http://nodejs.org/api/modules.html#modules_all_together.

Diese Funktionalität ist entscheidend, um die Integration des Typoskript-Compilers in andere Node-Packager wie Browserify zu ermöglichen. Der Patch von @ Nemo157 leistet gute Arbeit, ermöglicht jedoch kein einfaches Testen mit vorhandenen Paketierern, da die meisten zu späteren Versionen von Typoskript übergegangen sind und nicht mehr mit seinem Code kompatibel sind

Wo muss das Verzeichnis node_modules relativ zu den Quellen liegen?

Atom-TypeScript unterstützt jetzt typescript.definition out of the box. Einzelheiten: https://github.com/Microsoft/TypeScript/issues/2829

Sie können solche Pakete auch einfach mit Atom-Typoskript erstellen :rose: siehe wieder #2829

Einschränkung

Es funktioniert _einwandfrei_, wenn Sie ein Paket freigeben, das nicht von externen Bibliotheken abhängt. Wenn dies der Fall ist, benötigen wir einen Modulkonfliktlösungsalgorithmus.

Ich bin offen für Vorschläge für diesen Fall, aber mein Plan ist:

  • wir machen ein paar schlaue Sachen, indem wir so ein d.ts lesen und TypeScript nicht die externen reference Kommentare geben (z. B. node.d.ts hier https://github.com/TypeStrong/atom-typescript-examples /blob/master/node/node_modules/example-typescript-b/definition/sample-bdts) und stattdessen auf unser eigenes .d.ts zeigen, wenn wir es in unseren Typings haben.

Wird das für 2.0 auf Kurs bleiben? Es scheint ein wichtiges Feature für die Adoption von Node.j zu sein, was im Moment selbst mit DefinitelyTyped und dergleichen schmerzhaft ist.

Es scheint ein wichtiges Feature für die Adoption von Node.j zu sein, was im Moment selbst mit DefinitelyTyped und dergleichen schmerzhaft ist.

@LPGhatguy Siehe https://github.com/Microsoft/TypeScript/issues/2338. @vladima arbeitet daran, aber glaube nicht, dass ihm noch ein Meilenstein zugewiesen wurde :rose:

@LPGhatguy wir versuchen, dies in der nächsten Version zu bekommen. hoffentlich bald.

@mhegazy Du meinst 1,6? Das wäre großartig!

Bezieht sich das auf #2338?

yes für TypeScript 1.6 (zumindest versuchen wir das), ein yes für #2338; Es gibt ein paar andere Änderungen und Probleme, darunter # 3147 und # 4154

Warum wird es dann als TypeScript 2.0 als Meilenstein bezeichnet?

danke @heycalmdown , Meilenstein entfernt. Wir markieren Meilensteine ​​normalerweise nicht mit Vorschlägen. hoffentlich haben wir innerhalb einer Woche oder so ein Update zu diesem Thema. bleiben Sie dran.

Ich möchte mich einklinken und darum bitten, dass die Unterstützung des ES6-Moduls ebenfalls folgt (was ich vermute?).

Eingaben für

import mylib = require('mylib');
mylib.foo(mylib.bar);

sollte sich genauso verhalten wie

import { foo, bar } from 'mylib';
foo(bar);

Ich möchte mich einklinken und darum bitten, dass die Unterstützung für das ES6-Modul ebenfalls folgt (was ich annehme?

@DavidSouther Das wäre _automatisch_ der Fall. Die Suche zwischen den beiden ist konsistent :rose:

Dies wird von #4154 gehandhabt.

Wenn ich Nightly verwende, sollte ich ab morgen damit rechnen, dass das Importieren von Knotenmodulen "einfach funktioniert"?

Frage:
Ich denke, es ist eine gängige Konvention, Dateien zu benennen
"Index" im CommonJS und
"Haupt" in AMD
für kurze Wege.
In der Frage oben importiert der Autor
/node_modules/concator/index.ts als
import concator = require('concator');

Bitte verzeihen Sie mir - ich finde gerade heraus, ob jetzt auch die Index-Auflösung unterstützt wird und wie sieht es mit der Auflösung von index.ts oder main.ts in AMD aus?
Ich pinge auch @basarat an, um zu erfahren, ob es von https://github.com/TypeStrong/atom-typescript unterstützt wird/wird, da es mir jetzt nicht erlaubt, index.ts wie oben erwähnt anzufordern.

@sebilasse , wenn Sie heute typescript@next verwenden, sollte dies mit --module commonjs funktionieren

import concator = require('concator'); // resolves to node_modules/concator/index.ts

Es gibt keine Änderungen an der AMD-Auflösung gegenüber früheren Versionen.

@DavidSouther es sollte heute in typescript@next sein. probier es aus und lass uns wissen wie es gelaufen ist.

@mhegazy @basarat :+1: ok. Aber wie haltet ihr es mit der AMD-Auflösung für main.ts oder index.ts – sollte die nicht in Zukunft einheitlich sein?

@sebilasse , für AMD müssen wir meiner Meinung nach etwas tun, wie von @vladima in # 2338 (Abschnitt für: RequireJS/ES6-Modullader) angegeben.

Sehr schön!! \Ö/

@mhegazy Funktioniert immer noch nicht ganz so, wie ich es erwarte.

Ich habe https://github.com/DavidSouther/typescript-example-using-node mit meinem "idealen" Anwendungsfall zusammengestellt. tslib ist eine einfache Bibliothek, die eine einzelne Funktion exportiert. tsclient hängt von tslib sowie von readline aus den Node-Paketen ab. Das Setup-Skript ist bequem zu installieren, zu verknüpfen und auszuführen. Ich habe einen Lauf eingefügt und die unerwarteten Teile mit Inline-Kommentaren kommentiert.

% ./setup
...
> [email protected] build ~/ts-node/tslib
> tsc --version ; tsc -p src/

message TS6029: Version 1.7.0-dev.20150831
...
> [email protected] build /Users/southerd/devel/tmp/ts-node/tsclient
> tsc --version ; tsc -p src/

message TS6029: Version 1.7.0-dev.20150831
# Expect this to find tslib, but fail type checking.
# See tsclient/app.ts for details
src/app.ts(4,21): error TS2307: Cannot find module 'tslib'.

+ node ./dist/app.js # This works as expected!
What would you ask? What is the meaning of life?
42
+ set +x

Ich bekomme auch keine Sprachunterstützung für tslib-Importe in tsclient (VSCode Version 0.7.0 (0.7.0)), obwohl ich nicht ganz sicher bin, welches TSC verwendet wird oder wie ich das ändern kann.

@DavidSouther TypeScript-Compiler überprüft das Feld „typings“ in package.json, um „.d.ts“-Dateien zu finden. Mit dieser Änderung erhalte ich src/app.ts(13,7): error TS2322: Type 'string' is not assignable to type 'number'. , was wie ein legitimer Fehler aussieht

Ah, ich muss dieses Dokument übersehen haben. Ich habe immer noch das zweite Problem – wie ändere ich die VSCode tsc-Version?

Sie können VSCode über die Einstellung "typescript.tsdk" einen benutzerdefinierten TypeScript-SDK-Speicherort bereitstellen – er sollte auf den Ordner verweisen, der tsserver.js - und Standard-'.d.ts'-Dateien enthält. Falls TypeScript als npm-Paket installiert ist, sieht es so aus

// Place your settings in this file to overwrite the default settings
{   
    "typescript.tsdk": "C:\\Sources\\bugs\\node\\typescript-example-using-node\\tslib\\node_modules\\typescript\\lib"       
}

Hat jemand ein funktionierendes Muster hinbekommen? Ich habe den ganzen Nachmittag versucht, damit zu spielen, aber ich lande immer damit

error TS2307: Cannot find module

Im Moment befindet sich der Code in node_modules/my-module/. Und ich habe eine index.ts definiert, die sich um den Export kümmert, und ich habe in der package.json unter typescript.main darauf verwiesen. Im Consumer-Projekt habe ich versucht, {AClass} aus „my-module“ zu importieren; und import my-module = require('my-module'); Beide führen bei Typescript 1.7.0-dev.20150901 zum gleichen Fehler.

Beim Auflösen eines Moduls mit nicht relativem Namen sucht der Compiler mit --module commonjs nach einem .d.ts , das mit dem Namen in node_modules\name\index.d.ts übereinstimmt, oder sucht in package.json für eine Eigenschaft typings , und laden Sie die .d.ts, auf die sie zeigt.

Aus Ihrer Beschreibung geht hervor, dass Sie es auf index.ts setzen, Sie möchten Ihre Abhängigkeiten nicht wirklich kompilieren, Sie möchten nur ihre Eingaben verbrauchen, also sollten Sie es stattdessen auf index.d.ts setzen.

Ich habe die Schritte im Auflösungsalgorithmus des Knotenmoduls aktualisiert, um die Implementierung widerzuspiegeln: https://github.com/Microsoft/TypeScript/issues/2338

@ DavidSouther Ich habe anscheinend genau das gleiche Problem. Wenn ich mit einer Abhängigkeit in node_modules kompiliere, kann es das Modul nicht auflösen und gibt einen Fehler aus, aber dann generiert es immer noch das js, und wenn ich es ausführe, wird es ausgeführt. Vielleicht liegt es an meiner Einstellung, ich weiß es nicht. Meine d.ts ist größtenteils leer, ich habe eine index.ts, die sich um den Import und Reexport aller Klassen meiner Module kümmert, die in vielen .ts-Dateien definiert sind. Und dann verweist meine d.ts-Datei einfach auf diese index.ts und exportiert alles aus index.ts wie folgt:

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

declare module 'my_module' {
    export * from 'index';
}

Außerdem kompiliert es irgendwie immer noch die ts von node_modules, daher sollte ich eine saubere Aufgabe hinzufügen, um sie nach der Kompilierung zu löschen. Gibt es irgendwo eine Beschreibung der Funktion, die den Prozess zusammenfasst?

Bearbeiten: Ich habe es zum Laufen gebracht, aber es ist super hacky und gibt immer noch Fehler aus. Ich habe ein d.ts mit dts-generator erstellt und dann meine Klassen wie folgt importiert:

import MyClass from '../../node_modules/my_module/dist/MyClass';

Wenn ich import MyClass from 'my_module/MyClass' verwende, wird es ohne Fehler kompiliert, aber zur Laufzeit erhalte ich die Fehlermeldung Modul 'my_module/MyClass' kann nicht gefunden werden. Mit der obigen Lösung zeigt es direkt auf die kompilierte .js und zur Laufzeit funktioniert es irgendwie, obwohl es den Fehler ausgibt, dass das Modul zur Kompilierzeit nicht gefunden werden kann.

Ich habe immer noch Probleme beim Importieren von Submodulen (z. B. npm install angle2, import { Inject, Binding } from 'angular2/di' . Werde heute Abend daran arbeiten, einen enthaltenen Testfall zu erstellen.

Denken Sie nicht, dass angle seine Eingaben bereits so bündelt, wie es vom TypeScript-Compiler erwartet wird.

Das ist wahrscheinlich wahr; Ich werde mit ihnen zusammenarbeiten und sehen, wo es endet.

Diese Funktion funktioniert gut auf Typoskript 1.1, zum Beispiel https://github.com/Nemo157/typescript_w_node_modules_example

aber fehlgeschlagen in Typoskript 1.5.3, irgendetwas geändert?

------ aktualisieren ---------

Ich weiß, dass es in 1.6 veröffentlicht wird, danke

Ich kann dieses "halb funktionierende" nur in 1.6.2 bekommen

Zuerst packe ich eine Bibliothek mit einem my-lib.d.ts in das Verzeichnis dist und verweise auf diese Datei im package.json typings -Attribut der Datei package.json (zB "typings" : "dist/my-lib.d.ts" )

Dann importiere ich diese Bibliothek in eine Test.ts TypeScript-Datei mit

import { MyObject } from "my-lib"

MyObject wird ordnungsgemäß importiert und der js-Code wird bei der Transpilation ausgegeben.
Visual Studio Code bietet sogar die Vervollständigung von MyObject

Ich bekomme jedoch Compiler-Warnungen, die:
Test.ts(10,60): error TS2306: File '[]/node_modules/my-lib/dist/my-lib.d.ts' is not a module.

Visual Studio Code zeigt den Import tatsächlich als schwerwiegenden Fehler an

Alle importierten Module aus einem Knotenpaket müssen "externe Module" und keine "Umgebungsmoduldeklarationen" sein. dh keine declare module "foo" {.. } Deklarationen, sondern Import- oder Exportdeklarationen der obersten Ebene in der Datei.

Wenn also Ihr Paket "my-lib" in Typoskript geschrieben ist, bauen Sie es einfach mit --declarations und setzen Sie die Typisierungen auf die Datei .d.ts Ihres Hauptmoduls. Wenn nicht, und Ihre Eingaben sind etwas, das Sie von Hand verfasst oder von definitiv getippt haben, dann müssen Sie es entweder in ein externes Modul ändern oder warten, bis #4665 behoben ist (hoffentlich bald).

Der Grund für diese Einschränkung ist, dass dies später zu einer Verschmutzung des globalen Umfangs und zu Konflikten für Ihre Paketbenutzer führen kann. darüber gibt es eine lange Diskussion in #4665.

Hier ist eine Dokumentation für zukünftige Suchen: https://github.com/Microsoft/TypeScript/wiki/Typings-for-npm-packages

@mhegazy Vielen Dank für Ihre schnelle Antwort, die mir wirklich geholfen hat, den Build von Commonjs-Bibliotheken zu automatisieren, die in Typescript geschrieben sind und sowohl von Javascript- als auch von TypeScript-Code verwendet werden können.
import/export Syntax und Auflösung haben sich in letzter Zeit so schnell entwickelt, dass ich vermute, dass derzeit eine definitive Anleitung fehlt, wie man eine erstellt.

Ich habe es zum Laufen gebracht ... mit einer Einschränkung (und daher einer anderen Frage)

Hier ist eine vereinfachte Ansicht des Setups.

Die Bibliothek besteht aus drei Objekten A1, A2 und B in 2 Maschinenschriftdateien A.ts und B.ts; etwas wie

Quellen

A.ts

class A1{}
class A2{}
export { A1, A2 }

B.ts

class B{}
export { B }

Was wir zeigen wollen, wird in einem index.ts gesammelt:

export * from './A'
export * from './B'

bauen
Der Build wird mit Hilfe von grunt durchgeführt und die Flags --module commonjs und --declaration werden auf tsc 1.6.2 gesetzt
Das Endergebnis des Builds ist ein Baum, der aussieht wie

    package.json
    dist/
        js/
             A.js
             B.js
             index.js
        typings/
             A.d.ts
             B.d.ts
             index.d.ts

package.json enthält diese beiden Einträge:

"main": "dist/js/index.js",
"typings": "dist/typings/index.d.ts"

Die Verwendung dieser Bibliothek in TypeScript 1.6.2 mit einem einfachen import {A1, A2, B} from "mylib" funktioniert absolut einwandfrei. Abhängigkeiten auf mehreren Ebenen (dh Bibliotheken, die sich gegenseitig importieren) funktionieren ebenfalls einwandfrei.

Probleme treten auf, wenn die Bibliothek von einer anderen Bibliothek abhängt, die _keine_ TypeScript-Bibliothek ist.
Angenommen, die Bibliothek hängt von Node.js ab.
In einer der Quelldateien wird es einen Verweis auf die Typisierungen von NodeJS geben, zB
///<reference path="../typings/node/node.d.ts"/>

Nach der Transpilation wird diese <reference > Anweisung in der entsprechenden Deklarationsdatei landen; Das Problem ist, dass der Pfad zu node.d.ts wahrscheinlich falsch oder nicht vorhanden ist.
Gibt es dafür eine empfehlenswerte Vorgehensweise?

_Anmerkung_: Dieses Problem wird durch die Verwendung einer index.ts -Datei gemildert, um die interessanten Teile der Bibliothek offenzulegen, da index.ts keinen Grund hat, eine <reference > -Anweisung zu enthalten, und mit 1.6 .2 scheint es dem Compiler egal zu sein, dass Adts einen ungültigen Pfad in der Referenzanweisung hat

@bgrieder Wir behandeln dies in Phosphor mit tsconfig.json :
https://github.com/phosphorjs/phosphor-widget/blob/master/src/tsconfig.json

Wir fügen den kompilierten Dateien einfach alle externen Typisierungen hinzu, die wir benötigen. Dies bedeutet, dass, wenn einer dieser externen Typen Teil unserer öffentlichen Schnittstelle ist, die Verbraucher des Codes diese externen Typisierungen ebenfalls als Teil ihres Builds bereitstellen müssen. _Das ist okay_. Wenn wir diese Definitionen bündeln würden und eine andere vom Verbraucher verwendete Bibliothek _ebenfalls_ dieselben Definitionen bündeln würde, würde es zu Konflikten mit doppelten Symbolen kommen.

@sccolbert Ja!
Ich war besorgt, dass das Entfernen <reference ...> -Anweisungen die automatische Vervollständigung in allen IDEs unterbrechen würde, aber hey, nein: Zumindest Visual Studio Code 0.8.0 scheint intelligent genug zu sein, um diese Definitionen aus der tsconfig.json auszuwählen

Fertig mit reference . Exzellent !

@sccolbert

Was ist, wenn Sie ein einfaches Node.js -Projekt darin und *.d.ts dafür verwenden, wie hilft Ihnen die tsconfig -Lösung?

@heycalmdown Sie fügen einfach d.ts zum Feld files auf tsconfig hinzu, hier ist ein Beispiel, das dies tut:

https://github.com/phosphorjs/phosphor-widget/blob/master/test/src/tsconfig.json#L11
https://github.com/phosphorjs/phosphor-widget/blob/master/test/src/index.ts#L10

Beachten Sie, dass wir hier require anstelle von import verwenden müssen , nur weil die d.ts -Datei für Expect.js intern geschrieben ist.

Okay alles klar. Ihre Repositories sehen aus wie eine Art gutes Beispiel.

Wurde dies tatsächlich in TypeScript 1.6.2 implementiert?

Wenn ja, kann mir jemand sagen, was ich hier falsch mache?:
https://github.com/chanon/typescript_module_example

Sie möchten wahrscheinlich die es6-Importsyntax.

Am Mittwoch, 4. November 2015, 6:10 Uhr schrieb chanon [email protected] :

Wurde dies tatsächlich in TypeScript 1.6.2 implementiert?

Wenn ja, kann mir jemand sagen, was ich hier falsch mache?:
https://github.com/chanon/typescript_module_example


Antworten Sie direkt auf diese E-Mail oder zeigen Sie sie auf GitHub an
https://github.com/Microsoft/TypeScript/issues/247#issuecomment -153688004
.

Ich habe es gerade aktualisiert, um die es6-Importsyntax zu verwenden, und ich erhalte immer noch die gleichen Fehler (Modul kann nicht gefunden werden).

@chanon die package.json für node_modules Pakete müssen einen typings Schlüssel haben, der auf eine d.ts Datei zeigt, _nicht_ einen typescript Schlüssel, der zeigt .ts Dateien, wie Sie sie jetzt haben.

Wir verwenden die Knotenmodulauflösung ausschließlich in PhosphorJS (auf TS 1.6.2) und es funktioniert gut. Hier ist ein Beispiel: https://github.com/phosphorjs/phosphor-widget/blob/f908341cb1d46ada8ad8149e695a75e7ea2fde57/package.json#L6

Danke @sccolbert , aber mein ursprünglicher Vorschlag (ganz oben in dieser Ausgabe) bestand darin, eine typescript.main -Eigenschaft in package.json zuzulassen, die auf den wichtigsten TypeScript-Einstiegspunkt für geschriebene Knotenmodulpakete verweisen würde in TypeScript.

Dies würde den Import von TypeScript-Modulen in TypeScript-Code ermöglichen, ohne dass d.ts Typisierungsdateien erforderlich wären (es wäre nicht einmal erforderlich, sie zu generieren).

@chanon Ich habe nur darauf hingewiesen, was Sie tun müssen, um Ihren Code zum Laufen zu bringen.

@sccolbert Ich sehe danke.

Kann mir jemand, der sich damit auskennt, sagen, ob ich ein weiteres Problem erstellen soll, das diese spezielle Funktion anfordert?

Die wichtigsten Probleme mit der Modulauflösungslogik (außer dieser) scheinen # 2338 zu sein, das geschlossen ist, und # 5039, bei dem es anscheinend um die Unterstützung der Pfadauflösung im SystemJS-Stil geht, die sehr komplex aussieht.

Aber nur der einfache Import im CommonJS-Stil, wie ursprünglich in dieser Ausgabe gefordert, scheint vergessen worden zu sein? Zumindest der Teil über typescript.main und Ordner als Module?

Ich verstehe die Notwendigkeit (und den Wunsch) von d.ts-Dateien nicht, wenn sowohl das Modul als auch der Modulverbraucher bereits in TypeScript geschrieben sind.

Es unterscheidet sich eigentlich nicht wesentlich vom Importieren einer TypeScript-Datei relativ ex.

Anstatt zu tun:
import * as lib from '../relative/path/to/typescriptFile.ts'

Oder:
import * as lib from '../../node_modules/myModule/index.ts'

Lassen Sie TSC einfach in der Lage sein, die zu importierende Typoskript-Datei mit der normalen Pfadauflösung von node_modules zu finden. Und erlauben Sie zumindest den Import von Ordnern als Module (mit einem index.ts), damit ich im zweiten Beispiel Folgendes tun könnte:

import * as lib from 'myModule'

Oder liegt es an "Sie möchten Ihre Abhängigkeiten nicht wirklich kompilieren, Sie möchten nur ihre Eingaben verbrauchen"?

@chanon das Verhalten, das Sie skizzieren, ist das, was jetzt im Master ist. kannst du typescript@next ausprobieren?

Die ursprüngliche Implementierung von #2338 fügte einige zusätzliche Überprüfungen hinzu, um sicherzustellen, dass es sich um eine .d.ts-Datei handelt, und das hauptsächlich aus dem von Ihnen genannten Grund. Sie möchten nicht, dass Ihre Paketbenutzer Ihre "Quellen" bei jedem Compiler-Aufruf kompilieren und basierend auf ihren Compiler-Optionen unterschiedliche Ausgaben erhalten, Sie möchten nur Ihre Eingaben teilen.

Wenn Sie jedoch beide Pakete erstellen, möchten Sie dies möglicherweise tun, während Sie sie durchlaufen. Die Einschränkung wurde in #5278 entfernt.

Weitere Informationen finden Sie auf der Wiki-Seite zum Teilen von Eingaben über das npm-Paket: https://github.com/Microsoft/TypeScript/wiki/Typings-for-npm-packages

Danke für deine Klarstellung @mhegazy! Ich werde es ausprobieren.

@mhegazy Habe es gerade mit typescript@next versucht, funktioniert wie erwartet!

Das ist toll!!

Und vielen Dank an alle, die sich an diesem und verwandten Themen beteiligen :+1:

Ich habe dem obigen Problemtext ein Update hinzugefügt, um zu erklären, wie diese Funktion tatsächlich implementiert wurde.

Auf die Gefahr hin, in ein Minenfeld zu geraten, wie soll dies mit einfachen alten npm-Modulen funktionieren, die _keine_ Eigenschaft typings in package.json haben? Der Versuch, entweder tape oder get-parameter-names mit typescript@next zu verwenden, führt dazu, dass es mir in die Luft fliegt, da es diese Pakete nicht finden kann, weil sie das nicht haben Eigentum.

Sicher, sie sind keine Typoskript-Module, aber ich kann anscheinend keine Lösung finden, die einen erheblichen Teil des npm-Ökosystems sperrt.

@danpantry Normalerweise würden Sie eine normale .d.ts-Datei verwenden, die speziell für dieses Modul geschrieben wurde. Das DefinitelyTyped-Projekt enthält .d.ts-Dateien für viele gängige Module. Es gibt ein tsd-Dienstprogramm, das Ihnen bei der Installation und Verwaltung von .d.ts-Dateien von DefinitelyTyped helfen kann.

Sie können normale Module ohne Eingabe verwenden, indem Sie einfach die normale commonjs require-Syntax verwenden.

z.B
var moduleName = require("moduleName")

@chanon fühlt sich ein bisschen wie ein Hack an, um die 'klassische' require -Syntax zu verwenden, wenn ich die ES6-Syntax mit TypeScript verwende, damit ich JavaScript-Abhängigkeiten verwenden kann, aber danke. Ich habe vom Dienstprogramm tsd gehört, bin mir aber nicht sicher, wie sich das auf die Verwendung von ES6-Importen auswirken würde. Es sei denn, ich muss /// <reference path=... für diese Art von Modulen verwenden?

Ja das ist ein Weg. Eine andere Möglichkeit besteht darin, tsconfig.json-Dateien zu verwenden und Ihre tsd.d.ts-Stammdatei als erste Datei zu verwenden.

Sie könnten auch daran interessiert sein, dies zu lesen, das tsd und Typisierungen behandelt https://angularclass.com/the-state-of-typescript-packages/

@joewood danke für die Info, das letzte Mal, als ich mich mit Typoskript beschäftigt habe, war in den Tagen der einzelnen .d.ts -Dateien. ausgezeichneter Artikel

@chanon @danpantry Es ist etwas unglücklich, dass import foo = require('foo') (mit foo unter node_modules) nicht funktioniert, wenn foo's package.json keine Typisierungen hat.

@wmono gut, da vielleicht TypeScript 0.80 oder vielleicht früher import foo = require('foo') Syntax nur für den Import von Modulen mit Typisierungen war. Wenn es keine Eingaben hätte, würden Sie stattdessen var foo = require('foo') verwenden. Also ich würde sagen es ist einfach so.

@chanon Entschuldigung; Benutzerfehler. Es sah so aus, als ob Webpack mit dem "nackten" require zu kämpfen hatte, aber das Problem lag woanders.

Entschuldigung, kann jemand erklären, warum
var foo = require('foo');
Funktioniert für ein Standard-node_module ohne Typisierungen aber
import foo from 'foo';
nicht? Wurde das nur willkürlich definiert? Ich verstehe nicht, warum letzteres nicht funktionieren sollte - es ist mir egal, ob die externe JS-Bibliothek Typisierungen enthält oder nicht.

Entschuldigung, kann jemand erklären, warum
var foo = require('foo');
Funktioniert für ein Standard-node_module ohne Typisierungen aber
importiere foo aus 'foo';
nicht? Wurde das nur willkürlich definiert? Ich verstehe nicht, warum letzteres nicht funktionieren sollte - es ist mir egal, ob die externe JS-Bibliothek Typisierungen enthält oder nicht.

@harangue, weil var require eine der konkurrierenden Modulsyntaxen war (diese ist commonjs und andere in der Liste enthalten amd ), die _außerhalb des Typprüfungssystems_ unterstützt wurde. Wenn man das Typsystem verwenden möchte, würde man import require tun. Wenn ES6 den :hammer: nimmt und sagt, dass eine Syntax (:ring:) sie alle beherrscht ... ist es sinnvoll, dass diese Modulsyntax vom Typprüfungssystem standardmäßig unterstützt wird :rose:

@basarat Danke für die Klarstellung. Die Symbole waren auch hilfreich. ;) Ich bin mir immer noch nicht sicher, warum die ES6-Syntax eine Typprüfung vorschreibt. Was hindert den Compiler daran, zu sagen: "Oh, ich konnte keine Typdaten für dieses Modul finden, aber ich werde es trotzdem importieren". Welche Nebenwirkungen würde dieses (ziemlich intuitive, IMO) Verhalten nach sich ziehen?

Dies ist verwirrend für diejenigen (wie mich), die von ES6 zu TypeScript wechseln. Ich würde erwarten, dass sich die Importsyntax des ES6-Moduls in TypeScript genauso verhält, aber leider funktioniert es für die meisten npm-Pakete überhaupt nicht ...

aber leider funktioniert es für die meisten npm-Pakete überhaupt nicht ...

@teohhanhui Ich bin verwirrt. Können Sie ein konkretes Beispiel dafür geben, was Sie erreichen möchten und welchen Code Sie versucht haben, dies zu erreichen? Nur damit ich dir helfen kann :rose:

import koa from 'koa';

ergibt Cannot find module 'koa'. (2307) wenn target gleich es6 ist

koa ist (natürlich) in node_modules

Koa veröffentlicht jedoch keine Typescript-Typisierungen mit ihrem Projekt. Dies gilt nur für Pakete, die eine .d.ts-Datei mit ihrem Projekt veröffentlichen und in ihrer package.json auflisten. Da koa dies nicht tut, sollten Sie diese Typdefinitionen von Definitely Typed zusätzlich installieren.

Das scheint eine schlechte Entscheidung zu sein, da man erwarten würde, dass die import -Anweisung genauso funktioniert wie in einfachen ES6-Modulen. (Ja, ich weiß, die meisten der npm -Pakete sind CommonJS-Module, aber sie hier zu unterstützen, wäre immer noch sinnvoll.)

Ich bin neu bei TypeScript, also habe ich wahrscheinlich das falsche Verständnis, aber sind Typdefinitionen nicht optional? Warum kann ich das Paket nicht ohne die Typdefinition importieren? Ich möchte nicht gezwungen sein, Typdefinitionen zu suchen / zu erstellen.

Der Wechsel zur alten TS-Modul-Importsyntax ist keine Option, da dies bei Verwendung des es6 -Ziels nicht zulässig ist.

Ich bin neu bei TypeScript, also habe ich wahrscheinlich das falsche Verständnis, aber sind Typdefinitionen nicht optional?

Das ist falsch. Typdefinitionen _in Ihrem eigenen Code_ können implizit sein, was bedeutet, dass der Typescript-Compiler "es herausfindet". Sie werden niemals eine Bibliothek eines Drittanbieters durch den Typescript-Compiler übergeben, sodass der Compiler nie weiß, um welche Typen es sich handelt. Wenn Sie vorhaben, Code von Drittanbietern zu verwenden, sollten Sie wirklich lernen, wie Sie Definitely Typed und das tsd- Tool verwenden.

Was ist mit dieser Antwort von @basarat?

http://stackoverflow.com/a/27434010/1529493

Warum können Nicht-TypeScript-Module ohne Typdefinitionen nicht als solche importiert werden?

Sie können: const koa = require(‘koa’)

Am 21. Januar 2016 um 14:47 schrieb Teoh Han Hui [email protected] :

Warum können Module ohne Typdefinitionen nicht als solche importiert werden?


Antworten Sie direkt auf diese E-Mail oder zeigen Sie sie auf GitHub an: https://github.com/Microsoft/TypeScript/issues/247#issuecomment -173574234.

@bgrieder Ich beziehe mich auf die ES6-Importsyntax.

(das heißt, Sie verwenden commonjs), wenn nicht, verwenden Sie die Antwort declare var von Basarat

Am 21.01.2016, 14:48, Bruno Grieder bruno. [email protected] schrieb:

Sie können: const koa = require(‘koa’)

Am 21. Januar 2016 um 14:47 schrieb Teoh Han Hui < [email protected] [email protected] >:

Warum können Module ohne Typdefinitionen nicht als solche importiert werden?


Antworten Sie direkt auf diese E-Mail oder zeigen Sie sie auf GitHub an: https://github.com/Microsoft/TypeScript/issues/247#issuecomment -173574234.

Ich denke, der Punkt ist, dass eines der Ziele von TypeScript darin besteht, dass gültiges JS gültiges TS sein sollte. Für die ES6-Modulsyntax sollte TS diese mit oder ohne das Vorhandensein von Typdeklarationen kompilieren. Ohne Typdeklarationen sollte eine import -Anweisung einfach zu any werden.

Dem stimme ich vollkommen zu.

@ Joe Wood 👍

Am 21. Januar 2016 um 14:52 Uhr schrieb Joe Wood [email protected] :

Ich denke, der Punkt ist, dass eines der Ziele von TypeScript darin besteht, dass gültiges JS gültiges TS sein sollte. Für die ES6-Modulsyntax sollte TS diese mit oder ohne das Vorhandensein von Typdeklarationen kompilieren. Ohne Typdeklarationen sollte eine import-Anweisung einfach in any aufgelöst werden.

Dem stimme ich vollkommen zu.


Antworten Sie direkt auf diese E-Mail oder zeigen Sie sie auf GitHub an: https://github.com/Microsoft/TypeScript/issues/247#issuecomment -173575301.

FWIW dieses Verhalten (Erwartung, dass alle Bibliotheken von Drittanbietern im Voraus eingegeben werden) veranlasst mich, Flow über TypeScript zu verwenden. Obwohl TypeScript IDE-Unterstützung bietet, ist es nicht wirklich vernünftig zu erwarten, dass alles im Voraus eingegeben wird, insbesondere wenn es viele Bibliotheken gibt, die:

  • Sind nicht auf DefinitelyTyped
  • Sie haben keinen Ordner ./typings
  • Ich habe nicht die Zeit, es selbst zu tippen

Ich möchte lieber nicht gegen etwas kämpfen, das meine Entwicklung unterstützen soll.

@danpantry , warum deklarieren Sie nicht einfach Ihren lib-Einstiegspunkt als beliebig, und der Compiler wird damit zufrieden sein:

declare var $: any;

Das ist eine Problemumgehung. Aber ich denke, es wäre eine gute Idee für TypeScript, den ES6-Modulcode und den Fallback ordnungsgemäß zu respektieren. Ich sehe keinen guten Grund, warum eine Importanweisung nicht auf any zurückgreifen kann, anstatt einen Fehler zu melden, wenn das Modul der obersten Ebene nicht typisiert ist.

Ich würde es vorziehen, wenn der Compiler früh und laut fehlschlägt (das aktuelle Verhalten), anstatt dass sich Laufzeitprobleme unbemerkt einschleichen. Ich würde es vorziehen, explizit eine declare var foo: any -Zeile zu haben, um anzuzeigen: "Das ist unsicher, und ich weiß, was ich tue".

Warum nicht einfach die ES6-Importsyntax zulassen, wenn keine Eingaben verfügbar sind, und eine einfache Compiler-Warnung ausgeben, dass der Import in any aufgelöst wurde, anstatt einen „Emit-Verhinderungs“-Fehler auszugeben?

Am 21. Januar 2016 um 18:42 schrieb S. Chris Colbert [email protected] :

Ich würde es vorziehen, wenn der Compiler früh und laut fehlschlägt (das aktuelle Verhalten), anstatt dass sich Laufzeitprobleme unbemerkt einschleichen. Ich würde es vorziehen, explizit var foo: eine beliebige Zeile zu deklarieren, um anzugeben, dass "dies unsicher ist und ich weiß, was ich tue".


Antworten Sie direkt auf diese E-Mail oder zeigen Sie sie auf GitHub an: https://github.com/Microsoft/TypeScript/issues/247#issuecomment -173649845.

Jedenfalls behauptet der Compiler derzeit, dass er das Modul nicht finden kann, obwohl er sich in Wirklichkeit nur weigert, das Modul ohne Typdefinition zu importieren. Das ist nicht wirklich hilfreich, oder?

^^^ Das tausendmal. Es gab keinen Hinweis darauf, dass ich etwas falsch gemacht habe, als ich zum ersten Mal auf dieses Problem stieß. Es dauerte langes, hartes Googeln, um endlich herauszufinden, was los war (übrigens denke ich, dass dieses Problem einer der wenigen auffindbaren Orte ist, an denen es dokumentiert ist). Es ist so unnötig. Und mit Angular 2, das TypeScript mehr in den Mainstream bringt, kann ich mir nur vorstellen, wie viele Stack Overflow-Fragen aus diesem Verhalten entstehen werden.

Stimmen Sie der schlechten Fehlerbehandlungsbeschreibung sehr zu und importieren Sie sie einfach wie jede andere!

@sccolbert Ich stimme zu, dass es eine Benachrichtigung geben sollte, aber ich bin mir nicht sicher, ob es sich um einen Fehler handeln sollte - stattdessen vielleicht eine Warnung

Ich stimme @mhegazy und @sccolbert zu.

Mir wäre es viel lieber, wenn sich unsere Produktions-Build-Skripte (dh CI-Server) lautstark beschweren, wenn etwas nicht stimmt.

Hallo Leute,
Dieses Verhalten macht mich einfach wahnsinnig. Definitionsdateien sind nicht aktuell oder nicht in package.json registriert.
Am Ende erzeugt TypeScript JavaScript , also, bis wir alle zu dieser Sprache übergehen, seien Sie bitte sanft zum Rest der Welt, der Bibliotheken für die Muttersprache in anderen transpilierten Sprachen wie Ihrer bereitstellt .
Ich möchte wirklich wissen, ob TypeScript im JavaScript -Ökosystem bleiben möchte (ich würde sagen "integrieren", wie es aussieht, ist noch nicht da) oder ein Leben getrennt leben möchte, wie Die zweite Option wird mich dazu bringen, zu etwas anderem zu gehen.
Um das zu erreichen, reicht ein Schalter in der .tsconfig -Datei, dafür können wir sagen, ob wir strikte Importe wollen oder nicht.
Was CI laut Beschwerde betrifft, gibt es dafür Testframeworks in JavaScript . Wie auch immer, Sie erhalten keine Typprüfung zur Laufzeit, die schlechte Importprüfung ist das weniger wichtige Problem.
Alles Gute.

@devel-pa, die Fehler sollen Ihnen sagen, dass der Compiler keine Ahnung hat, was Ihr Import ist. eine spätere Verwendung des Imports kann nicht überprüft werden.

Das Abschalten der Fehler löst keine Probleme. es schiebt diese "Unbekannten" einfach stillschweigend durch Ihr System. Ohne Typinformationen kann der Compiler Sie nicht davor warnen, was sicher ist und was nicht. und das ist der Sinn von TypeScript :)

Wie für generiertes JS. keiner der Fehler vom Typ TS verhindert, dass Ihre Ausgabe generiert wird. Wenn Sie sich nicht um die Typfehler kümmern, ignorieren Sie sie einfach alle. Der Compiler generiert weiterhin Ihre passenden .js-Dateien.

Die Lösung für fehlende Definitionen besteht darin, sie zu deklarieren. Sie müssen nicht die vollständige Form des Moduls deklarieren, sondern nur den Namen. Dadurch kann der Compiler wissen, dass es ein Modul "myLibrary" gibt, er kann Sie vor Tippfehlern in Modulnamen warnen, und was noch wichtiger ist, keine anderen Module würden ungeprüft bleiben.

declare module "myLibrary" {
    var a: any;
    export = a;
}

wie in #6615 beschrieben, sollte TypeScript bald eine kürzere Form davon unterstützen.

Ich denke, das Problem ist der Schmerz, den dies für Onboarding-Projekte verursacht. Ich denke, dieses Problem ist analog zu implizit jedem . Im Moment sind diese Importe im Wesentlichen stillschweigend nichtig . Sicher, die Fehler können ignoriert werden, aber das verursacht viel Lärm und widerspricht der Philosophie des schrittweisen Tippens und gültiges JS ist gültiges TS.

Ich kann die Verwirrung hier für Leute verstehen, die neu bei TS sind. Wenn sie die ES6-Modulsyntax aktiv in JS verwendet haben, warum funktioniert sie dann nicht einfach in TS? Was ist das Besondere an import from gegenüber var x = require - was _als_ implizites Any behandelt wird. Ursprünglich war import ein TS-spezifisches Schlüsselwort, was implizierte, dass der Entwickler wollte, dass das Modul als typisiertes Modul behandelt wird. Jetzt, da es nicht exklusiv für TS ist, glaube ich nicht, dass diese Annahme gemacht werden kann.

Implizite Fehler treten bei Variablendeklarationen ohne Typ auf. aber die Verwendung einer nicht deklarierten Variablen ist auch heute noch ein Fehler. Für jquery benötigen Sie immer noch irgendwo declare var $; , damit der Compiler weiß, dass Sie wirklich eine globale Variable namens $ haben wollten und sie nicht nur falsch eingegeben haben. es ist mehr oder weniger dasselbe für Module, der Compiler muss wissen, dass es ein Modul namens "myLibrary" gibt und das kein falsch geschriebener Name ist. Fügen Sie also einfach eine Deklaration dafür hinzu.

Auf jeden Fall sollte #6615 das Hinzufügen declare module "*"; unterstützen, um allen Modulen in Ihrem System zu entsprechen, obwohl ich denke, wenn Sie das tun, erhalten Sie keine Hilfe von Ihren Werkzeugen und Sie stellen sich auf eine schmerzhafte Situation ein Übergang später, wenn Sie sich entscheiden, es zu entfernen.

@mhegazy Ich verstehe deine Argumentation, aber ich habe wirklich ein Problem mit dieser Begründung

Im Grunde sagen Sie uns, dass wir eine "Platzhalter"-Moduldefinition entwerfen sollen, und das Problem wird verschwinden.
Dieses Risiko besteht darin, dass sich diese "Platzhalter"-Definitionen nach einer Weile bei einem vernünftig großen Projekt einfach einschleichen und in einem Typing-Verzeichnis begraben werden. Wenn es keine Warnungen mehr gibt, wird jeder sie einfach vergessen, und wenn ein Problem auftritt, wird es einfach mühsam sein, jede Moduldefinition durchzugehen, um zu sehen, welches ein Platzhalter ist.

Noch schlimmer ist die Situation bei typisierten Modulen (diejenigen mit dem typings -Eintrag in package.json), von denen wir annehmen würden, dass sie richtig typisiert sind, diese Platzhalter tatsächlich intern verwenden könnten.

Ich verstehe, dass diese Platzhalter nicht verhindert werden können, aber ich würde es vorziehen, wenn sie zumindest nicht gefördert würden.
Was befürwortet werden sollte, ist, dass der Import standardmäßig zu any wird und dass der Compiler bei jeder Kompilierung eine Warnung ausgibt. Wenn wir uns also die Compiler-/CI-Protokolle ansehen, wissen wir zumindest, dass etwas möglicherweise faul ist und verbessert werden muss.

(nebenbei, wie auf der Homepage von typescriptlang.org angegeben, Typescript ist eine „Obermenge“ von Javascript, und meiner Meinung nach sollte jede gültige ES6-Syntax einfach so geschluckt werden, wie sie ist.)

Workarounds und das Verstecken des Mülls unter dem Teppich sind für mich das Schlimmste was passieren kann (neben ES6 super).
Ich arbeite die ganze Zeit mit JS-Bibliotheken und normalerweise mit den letzten Versionen als Teil meines Jobs und zusätzlicher Codierung zu Hause. 90 % sind nicht typisiert oder haben alte Defs, 9 % sind nicht sehr gut typisiert (da der Compiler nicht weiß, dass er eine Def für alle Dateien erstellen muss). Keine meiner hat sehr gute Defs, aus dem gleichen vorherigen Grund und aus dem Grund, dass mein Ziel JS ist, denke ich nicht, dass ich mich um die Originalsprache kümmern muss.
Außerdem habe ich den Grund dafür gesehen, dass es "unbekannte" Bibliotheken gibt. Nein, überhaupt nicht, wenn die Entwickler nicht wissen und verstehen, welche Libs verwendet werden, warum sollten sie sich dann mit ihnen beschäftigen, ich weiß, warum ich Sachen verwende und warum ich sie dem Stack hinzufüge. Warnung und Tests (falls vorhanden) reichen dafür aus.
Bitte JavaScript zuerst, das ist das Ziel und das Ökosystem. TS ist nur ein Zubehör für eine bessere Codierung und Typprüfung zur Kompilierzeit, aber nur für das, was wir bauen. Der Rest ist nichts mit Typoskripten.
Ich möchte erwähnen, dass ich auch gegen nmps peerDependencies war, ich bin derjenige, der gewählt hat, nicht die Software. Imperative Programmierung, Baby.

Was ist mit dem Importieren von Modulen aus dem JSPM-Verzeichnis anstelle von node_modules?

Bearbeiten: Ich habe ein vorhandenes Ticket gefunden -> https://github.com/Microsoft/TypeScript/issues/6012

Ich bin gerade auf ein Problem mit der Knotenmodulauflösung gestoßen, als ich SystemJS zum Laden eines Verzeichnisses verwendet habe:

Während Node (und damit TypeScript) offensichtlich versteht, dass der Pfad tatsächlich ein Verzeichnis ist und daher stattdessen index.ts lädt, tut SystemJS dies nicht, was bedeutet, dass gültiger TS-Code tatsächlich nicht im Browser geladen werden kann.

Dies gilt auch für Knotenmodule, die einen index.ts/js-Einstiegspunkt haben oder sogar die Eigenschaft package.json main verwenden. Dies ist etwas einfacher zu handhaben, da es einfach (wenn auch wiederholt) ist, eine Paketkonfiguration zu SystemJS hinzuzufügen. Das ist nicht so einfach, wenn man mit beliebigen Verzeichnissen arbeitet.

Was ist die passende Lösung dafür?

Die automatische Modulauflösung von JSPM wird derzeit nicht unterstützt. dies wird von https://github.com/Microsoft/TypeScript/issues/6012 verfolgt.

Es wird empfohlen, die Auflösungsunterstützung für das Pfadzuordnungsmodul zu verwenden, siehe https://github.com/Microsoft/TypeScript-Handbook/blob/release-2.0/pages/Module%20Resolution.md#path -mapping

Die obigen Anweisungen sind ein Anfang, aber einige Leute müssen möglicherweise etwas zusätzliches tun ... Sie müssen möglicherweise hinzufügen
<Folder Include="node_modules" />
zu .njsproj

Mehr Info

Ich habe mit Schluck gebaut und hatte TypeScriptCompileBlocked in .nsproj. Um Probleme beim Debuggen von Haltepunkten in VS 15 Preview 5 (ich bekam den Fehler „Frame not in module“ zu bekommen) und Probleme mit Intellisense zu beheben, musste ich hinzufügen zu .njsproj . Dieses Verzeichnis war bereits vorhanden, als ich das Projekt importierte, war aber auf git-ignore gesetzt. Das ist meine Theorie, warum Visual Studio es ignoriert hat (vielleicht sollte es eine automatische Ausnahme für node_modules haben?)

Abgesehen von Debugging und Intellisense-Funktion habe ich auch aufgehört, Intellisense-Fehler zu sehen, die über dieselben genauen Fehler hinausgingen, die ich beim Erstellen von Gulp gesehen habe, was zu erwarten ist.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen