TypeScript Deklarationsdateien

Die Deklarationsdatei ist derÜbersetzer zwischen TypeScript- und JavaScript-Bibliotheken, die TypeScript mitteilt, welche Funktionen eine JavaScript-Bibliothek bereitstellt, welche Typen die Parameter haben und welche Typen die Rückgabewerte haben.


Beginnen wir mit einem Problem.

Angenommen, Sie schreiben ein Projekt in TypeScript und müssen eine JavaScript-Bibliothek eines Drittanbieters (z. B. jQuery) einbinden. Dann könnten Sie Code wie diesen schreiben:

$('#foo');
// oder 
jQuery('#foo');

Dieser Code funktioniert in einem reinen JavaScript-Projekt einwandfrei, aber in einer TypeScript-Datei führt er direkt zu einem Fehler:

jQuery('#foo');

// index.ts(1,1): error TS2304: Cannot find name 'jQuery'.

Warum verursacht es einen Fehler? Weil TypeScript nicht erkennt,$undjQuerywas es ist.

TypeScripts Kernfunktion ist die Typprüfung – TypeScript muss zur Kompilierungszeit den Typ jeder Variable und jeder Funktion kennen. Aber jQuery ist eine reine JavaScript-Bibliothek ohne Typinformationen, daher kann TypeScript sie natürlich nicht verstehen.


Schnelle Lösung: das Schlüsselwort declare

Der einfachste Weg ist, das Schlüsselwortdeclarezu verwenden, um TypeScript manuell mitzuteilen: „Diese Variable existiert, und ihr Typ ist so“:

declare var jQuery: (selector: string) => any;

jQuery('#foo');

Die Bedeutung dieser Codezeile ist: Deklariere eine VariablejQuery, die eine Funktion ist, welche einen Parameter vom Typstringannimmt, und der Rückgabewert kann einen beliebigen Typ haben (any)。

Jetzt meldet TypeScript keinen Fehler mehr, weil der Compiler bereits weiß, welchen Typ jQuery hat.

declareTypen, die mit dem Schlüsselwort deklariert werden, wirken nur zur Kompilierzeit; sie werden im kompilierten JavaScript-Code vollständig entfernt und haben keinen Einfluss auf das Laufzeitverhalten.

Der kompilierte JavaScript-Code des obigen Beispiels ist:

jQuery('#foo');

Wie Sie sehen können,declare-Anweisung ist verschwunden, sodass nur der eigentliche aufrufende Code übrig bleibt.

Aberdeclarekann nur das temporäre Problem einer einzelnen Datei lösen. Wenn eine Bibliothek viele Methoden und viele Klassen hat, ist es offensichtlich unrealistisch, declare manuell in jeder Datei zu schreiben. Hier kommen Deklarationsdateien ins Spiel.


Deklarationsdateien: eine endgültige Lösung

Eine Deklarationsdatei fasst alledeclare-Deklarationen in einer einzigen separaten Datei zusammen, und jede TypeScript-Datei im Projekt kann darauf verweisen.

⟦0┧Dateinamenskonventionen

Declaration files uniformly use.d.tsas the suffix,dwhich stands for declaration. For example:

example.d.ts

Grundlegende Syntax

⟦0┧Die Syntax zum Deklarieren eines Moduls lautet wie folgt:

declare module Module_Name {
}

⟦0┧Verwenden Sie in einer TypeScript-Datei die Triple-Slash-Direktive, um die Deklarationsdatei einzubinden:

/// <reference path = "example.d.ts" />

⟦0┧Die Triple-Slash-Direktive ist eine TypeScript-spezifische Syntax, die verwendet wird, um den Compiler anzuweisen, die angegebene Deklarationsdatei während der Kompilierung einzubinden.

Declaration files for many popular third-party libraries (such as jQuery, Lodash) are already maintained by the community and stored inDefinitelyTypeddas Projekt. Sie müssen nur das entsprechende@types/xxx-Paket über npm installieren, und Sie können es verwenden, ohne es manuell zu schreiben.


Vollständiges Beispiel: Deklarationsdateien von Grund auf erstellen

Das folgende vollständige Beispiel demonstriert den gesamten Prozess des Erstellens und Verwendens einer Deklarationsdatei.

Der gesamte Prozess umfasst die folgenden Dateien:

DateiZweck
CalcThirdPartyJsLib.jsJavaScript-Bibliothek eines Drittanbieters (reines JS, keine Typinformationen)
Calc.d.tsDeklarationsdatei (manuell geschrieben, beschreibt die Typen der Bibliothek)
CalcTest.tsTypeScript-Anwendungscode (verweist auf die Deklarationsdatei, ruft die Bibliothek auf)
CalcTest.jsKompilierte Ausgabe (von tsc kompilierte JS-Datei)
example.htmlFertige Seite läuft im Browser

Schritt 1: Die JavaScript-Bibliothek eines Drittanbieters erstellen

Angenommen, wir haben eine Bibliothek eines Drittanbieters, die kumulative Summierungsfunktionalität bereitstellt. Sie verwendet den NamespaceExample, um Code zu organisieren und Namenskonflikte bei Variablen zu vermeiden:

Code der Datei CalcThirdPartyJsLib.js:

// Dateipfad: CalcThirdPartyJsLib.js
// Dies ist eine simulierte JavaScript-Bibliothek eines Drittanbieters

// Die Example-Namespace-Variable deklarieren (ein leeres Objekt erstellen, falls es nicht existiert)
var Example;

// Einen sofort ausgeführten Funktionsausdruck (IIFE) verwenden, um den Code zu kapseln und zu verhindern, dass interne Variablen in den globalen Gültigkeitsbereich gelangen
(function(Example) {
    // Calc-Konstruktor, wird zum Erstellen von Rechnerobjekten verwendet
    var Calc = (function () {
        function Calc() {
            // Derzeit werden keine Initialisierungsparameter benötigt; der Konstruktor wird für zukünftige Erweiterungen beibehalten.
        }
    })

    // doSum-Methode: berechnet die Summe aller ganzen Zahlen von 0 bis limit
    // limit (erforderlich): die Obergrenze der Summe, inklusive
    // Beispiel: Bei limit=10 wird 0+1+2+...+10 = 55 berechnet
    Calc.prototype.doSum = function (limit) {
        var sum = 0;

        for (var i = 0; i <= limit; i++) {
            sum = sum + i;
        }
        return sum;
    }

    // Den Calc-Konstruktor an den Example-Namespace anhängen
    // Auf diese Weise können von außen über new Example.Calc() Instanzen erstellt werden
    Example.Calc = Calc;
    return Calc;
})(Example || (Example = {}));

// Interner Selbsttest-Code der Bibliothek
var test = new Example.Calc();

Diese Bibliothek verwendet ein gängiges Muster: den sofort ausgeführten Funktionsausdruck (IIFE). Einfach ausgedrückt: Sie packt den Code in eine Funktion und führt ihn sofort aus, sodass Variablen, die innerhalb der Funktion definiert sind, nicht nach außen gelangen und Namenskonflikte mit anderem Code vermieden werden.

Schritt 2: Die Deklarationsdatei schreiben

Jetzt haben wir eine JS-Bibliothek, aber sie hat keine Typinformationen. Wir müssen eine Deklarationsdatei erstellen, die nur die "Form" der Bibliothek beschreibt – welche Klassen es gibt, welche Methoden es gibt, welchen Typ die Parameter und Rückgabewerte haben –, aber keine tatsächliche Codelogik enthält:

Code der Datei Calc.d.ts:

// Dateipfad: Calc.d.ts
// Dies ist eine Deklarationsdatei; sie enthält nur Typinformationen, keinen ausführbaren Code

// Das Example-Modul deklarieren, das dem Example-Namespace in der JS-Bibliothek entspricht
declare module Example {
   // Die Calc-Klasse deklarieren, um TypeScript mitzuteilen, dass diese Klasse mit new instanziiert werden kann
   export class Calc {
      // Deklariere die doSum-Methode: nimmt einen number-Parameter und gibt einen number-Wert zurück
      // Hinweis: Hier wird nur die Methodensignatur deklariert, ohne einen Methodenrumpf (geschweifte Klammern)
      doSum(limit: number): number;
   }
}

Der größte Unterschied zwischen einer Deklarationsdatei und einer normalen .ts-Datei: Eine Deklarationsdatei enthält nur Typsignaturen, keinen Implementierungscode. Sie beantwortet nur "wie diese Funktion aussieht", nicht "was diese Funktion tut".

Schritt 3: In TypeScript-Code verwenden

Schreiben Sie nun Business-Code. Nachdem Sie die Deklarationsdatei referenziert haben, können Sie diese JS-Bibliothek eines Drittanbieters wie eine native TypeScript-Bibliothek verwenden:

Code der Datei CalcTest.ts:

// Dateipfad: CalcTest.ts
// Triple-Slash-Direktive: weist den TypeScript-Compiler an, die Deklarationsdatei einzubinden
/// <reference path = "Calc.d.ts" />

// Eine Calc-Instanz erstellen; TypeScript kann jetzt den Typ von obj korrekt erkennen
var obj = new Example.Calc();

// obj.doSum("Hello"); // Kompilierungsfehler! "Hello" ist ein String, aber doSum erfordert ein Argument vom Typ number
console.log(obj.doSum(10)); // Korrekter Aufruf: 10 übergeben, 55 erwartet

Achte auf die auskommentierte Zeile:

obj.doSum("Hello");

Wenn du diese Zeile aus dem Kommentar nimmst, meldet TypeScript während der Kompilierung einen Fehler, weil die Deklarationsdatei bereits angibt, dass doSum nur einen Parameter vom Typ number akzeptiert. Das ist die Typprüfung, die dich schützt – Fehler werden schon beim Schreiben des Codes sichtbar, statt zur Laufzeit im Browser abzustürzen.

Schritt 4: TypeScript kompilieren

Verwende den integriertentsc-Befehl zum Kompilieren:

tsc CalcTest.ts

Nach der Kompilierung wird dieCalcTest.js-Datei mit folgendem Inhalt erzeugt:

Kompilierte Ausgabe von CalcTest.js:

// Dateipfad: CalcTest.js (automatisch vom tsc-Befehl generiert)
/// <reference path = "Calc.d.ts" />
var obj = new Example.Calc();
//obj.doSum("Hello"); // Kompilierungsfehler
console.log(obj.doSum(10)); // Ausgabe: Gibt 55 auf der Konsole aus

Man kann sehen, dass die Triple-Slash-Direktiven und Typinformationen in den Deklarationsdateien aus der kompilierten Ausgabe entfernt wurden, sodass nur reiner JavaScript-Laufzeitcode übrig bleibt.

Schritt 5: Im Browser ausführen

Erstellen Sie schließlich eine HTML-Seite, um alle JS-Dateien miteinander zu verknüpfen:

Beispiel

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Beispiel-Tutorial (example.com)</title>
<!-- Schritt 1: Die Bibliothek eines Drittanbieters laden, um den Example-Namespace global verfügbar zu machen -->
<script src = "CalcThirdPartyJsLib.js"></script>
<!-- Schritt 2: Den kompilierten Business-Code laden -->
<script src = "CalcTest.js"></script>
</head>
<body>
    <h1>Deklarationsdatei-Test</h1>
    <p>Probieren wir es aus.</p>
</body>
</html>

Öffnen Sie diese HTML-Datei in einem Browser, öffnen Sie die Konsole (F12), und Sie können die Ausgabe sehen:

55

Dies ist der Rückgabewert von doSum(10): 0+1+2+...+10 = 55.

声明文件测试结果


Zusammenfassung

Eine Deklarationsdatei ist im Wesentlichen ein "Typ-Handbuch", das es TypeScript ermöglicht, reine JavaScript-Bibliotheken zu verstehen und zu prüfen.

Der gesamte Workflow lässt sich in drei Schritten zusammenfassen:

1. Besorgen Sie sich eine JS-Bibliothek und analysieren Sie, welche APIs sie offenlegt.

2. Schreiben Sie.d.tseine Deklarationsdatei, die die Typsignaturen dieser APIs beschreibt.

3. Verweisen Sie im TypeScript-Code auf die Deklarationsdatei, um vollständigen Schutz durch Typprüfung zu genießen.

Für häufig verwendete Drittanbieter-Bibliotheken in der täglichen Entwicklung verfügt die überwiegende Mehrheit bereits über fertige Deklarationsdateien (installiert übernpm install @types/xxx). Nur wenn Sie eine sehr obskure Bibliothek oder eine interne private Bibliothek verwenden, müssen Sie Deklarationsdateien manuell schreiben.

Andere Erweiterungen