Das Repository für hochwertige TypeScript-Typdefinitionen.
Sie können diese README-Datei auch auf Español, 한국어, Русский, 简体中文, Portugiesisch, Italiano, 日本語 und Französisch lesen!
Link zum Admin-Handbuch
Definitely Typed wurde kürzlich in ein richtiges pnpm
Monorepo geändert; Möglicherweise möchten Sie dieses Dokument erneut lesen, um Änderungen am Layout der Pakete in diesem Repo zu erfahren.
Zumindest möchten Sie möglicherweise das Repository git clean -fdx
(oder node ./scripts/clean-node-modules.js
unter Windows) aufrufen, um node_modules
zu bereinigen und pnpm install --filter .
um das Arbeitsbereichsstammverzeichnis zu installieren. Weitere Informationen zur pnpm install
finden Sie in den weiteren Abschnitten.
In diesem Abschnitt wird der Zustand des Repositorys und des Veröffentlichungsprozesses verfolgt. Es kann für Mitwirkende hilfreich sein, die Probleme mit ihren PRs und Paketen haben.
Wenn hier irgendetwas falsch zu sein scheint oder einer der oben genannten Punkte fehlschlägt, teilen Sie uns dies bitte im Definitely Typed-Kanal auf dem TypeScript Community Discord-Server mit.
Weitere Informationen finden Sie im TypeScript-Handbuch.
Dies ist die bevorzugte Methode. Zum Beispiel:
npm install --save-dev @types/node
Um Typisierungen für ein bereichsbezogenes Modul zu installieren, entfernen Sie das @
und fügen Sie nach dem Bereich einen doppelten Unterstrich hinzu. Um beispielsweise Typisierungen für @babel/preset-env
zu installieren:
npm install --save-dev @types/babel__preset-env
Die Typen sollten dann automatisch vom Compiler eingebunden werden. Möglicherweise müssen Sie eine types
hinzufügen, wenn Sie keine Module verwenden:
/// <reference types="node" />
Weitere Informationen finden Sie im Handbuch.
Für ein NPM-Paket „foo“ erfolgen die Eingaben dafür unter „@types/foo“.
Wenn Ihr Paket über Typisierungen verfügt, die mithilfe des Schlüssels types
oder typings
in seiner package.json
angegeben wurden, zeigt die npm-Registrierung an, dass für das Paket Bindungen wie folgt verfügbar sind:
Sie können das gesamte Repository wie gewohnt klonen, es ist jedoch groß und enthält ein riesiges Verzeichnis mit Typpaketen. Das Klonen dauert einige Zeit und kann unnötig unhandlich sein.
Für einen besser verwaltbaren Klon, der nur die für Sie relevanten Typpakete enthält, können Sie sparse-checkout
und --filter
Funktionen von Git verwenden. Dadurch wird die Klonzeit verkürzt und die Git-Leistung verbessert.
️ Dies erfordert mindestens Git-Version 2.27.0, die auf den meisten Computern wahrscheinlich neuer als die Standardversion ist. Kompliziertere Verfahren sind in älteren Versionen verfügbar, werden jedoch in diesem Handbuch nicht behandelt.
git clone --sparse --filter=blob:none <forkedUrl>
--sparse
initialisiert die Sparse-Checkout-Datei, sodass das Arbeitsverzeichnis nur mit den Dateien im Stammverzeichnis des Repositorys beginnt.--filter=blob:none
schließt den gesamten Commit-Verlauf ein, schließt jedoch Dateien aus und ruft sie nur bei Bedarf ab.git sparse-checkout add types/<type> types/<dependency-type> ...
pnpm test <package to test>
aus. Wenn Sie eine PR erstellen, um ein vorhandenes Paket zu bearbeiten, sollte dt-bot
die Besitzer des Pakets @-erwähnen. Wenn dies nicht der Fall ist, können Sie dies selbst im Kommentar zur PR tun.
Wenn Sie der Autor der Bibliothek sind und Ihr Paket in TypeScript geschrieben ist, bündeln Sie die generierten Deklarationsdateien in Ihrem Paket, anstatt sie auf Definitely Typed zu veröffentlichen. Sie können Deklarationsdateien auch aus JavaScript-Dateien generieren und dabei JSDoc für Typanmerkungen verwenden.
Wenn Sie Typisierungen für ein npm-Paket hinzufügen, erstellen Sie ein Verzeichnis mit demselben Namen. Wenn sich das Paket, für das Sie Typisierungen hinzufügen, nicht auf npm befindet, stellen Sie sicher, dass der von Ihnen gewählte Name nicht mit dem Namen eines Pakets auf npm in Konflikt steht. (Sie können npm info <my-package>
verwenden, um zu überprüfen, ob das Paket <my-package>
vorhanden ist.)
Ihr Paket sollte diese Struktur haben:
Datei | Zweck |
---|---|
index.d.ts | Darin sind die Typisierungen für das Paket enthalten. |
<my-package>-tests.ts | Dieser enthält Beispielcode, der die Eingaben testet. Dieser Code wird nicht ausgeführt, aber er wird typgeprüft. |
tsconfig.json | Dadurch können Sie tsc innerhalb des Pakets ausführen. |
.eslintrc.json | (Selten) Wird nur benötigt, um für eslint geschriebene Lint-Regeln zu deaktivieren. |
package.json | Enthält Metadaten für das Paket, einschließlich Name, Version und Abhängigkeiten. |
.npmignore | Gibt an, welche Dateien in das Paket aufgenommen werden sollen. |
Generieren Sie diese, indem Sie npx dts-gen --dt --name <my-package> --template module
ausführen. Alle Optionen finden Sie unter dts-gen.
Wenn Sie neben index.d.ts
auch .d.ts
Dateien verfügen, stellen Sie sicher, dass diese entweder in index.d.ts
oder den Tests referenziert werden.
Definitely Typed-Mitglieder achten regelmäßig auf neue PRs. Beachten Sie jedoch, dass die Anzahl anderer PRs die Arbeit verlangsamen kann.
Ein gutes Beispielpaket finden Sie unter base64-js.
Wenn ein Paket seine eigenen Typen bündelt, sollten Typen aus Definitely Typed entfernt werden, um Verwirrung zu vermeiden.
Sie können es entfernen, indem Sie pnpm run not-needed <typingsPackageName> <asOfVersion> [<libraryName>]
ausführen.
<typingsPackageName>
: Dies ist der Name des zu löschenden Verzeichnisses.<asOfVersion>
: Mit dieser Version wird ein Stub unter @types/<typingsPackageName>
veröffentlicht. Sollte höher sein als jede derzeit veröffentlichte Version und eine Version von <libraryName>
auf npm sein.<libraryName>
: Name des npm-Pakets, das die Definitely Typed-Typen ersetzt. Normalerweise ist dies identisch mit <typingsPackageName>
. In diesem Fall können Sie es weglassen. Wenn ein Paket noch nie auf Definitely Typed war, muss es nicht zu notNeededPackages.json
hinzugefügt werden.
Testen Sie Ihre Änderungen, indem Sie pnpm test <package to test>
ausführen, wobei <package to test>
der Name Ihres Pakets ist. Sie müssen dies aus dem DefinitelyTyped-Verzeichnis ausführen, da einzelne package.jsons keine Testskripts definieren.
Dieses Skript verwendet dtslint, um den TypeScript-Compiler für Ihre DTS-Dateien auszuführen.
Sobald Sie alle Ihre Änderungen fertig haben, verwenden Sie pnpm run test-all
um zu sehen, wie sich Ihre Änderungen auf andere Module auswirken.
attw
) prüft dtslint umfasst Modulformat- und package.json
Konfigurationsprüfungen von @arethetypeswrong/cli. Die Prüfungen werden nur ausgeführt, wenn auf npm ein mit SemVer-Major kompatibles Implementierungspaket zum Vergleich mit dem DefinitelyTyped-Paket gefunden werden kann. (DefinitelyTyped-Pakete, die in ihrer package.json
als nonNpm
markiert sind, werden übersprungen.)
Viele Pakete bestehen derzeit die attw
-Prüfungen nicht und müssen repariert werden. Damit wir schrittweise Fortschritte machen können, schlagen fehlgeschlagene attw
Prüfungen bei der dtslint
-Ausführung nicht fehl, wenn das Paket in failingPackages
in attw.json
aufgeführt ist. Sie werden jedoch weiterhin in der Ausgabe von pnpm test my-package
gemeldet. Wenn Sie das Paket reparieren, entfernen Sie es aus failingPackages
damit attw
-Prüfungen fehlgeschlagene dtslint
-Ausführungen starten können.
Bei allen von attw
gemeldeten Problemen ist die Dokumentation in der Ausgabe verlinkt. Einige Faustregeln zur Vermeidung von Problemen:
Die package.json
im DefinitelyTyped-Paket muss über übereinstimmende type
und exports
verfügen, wenn das Implementierungspaket diese in seiner package.json
verwendet. Wenn eine Implementierung package.json
beispielsweise so aussieht:
{
"name" : " my-package " ,
"version" : " 1.0.1 " ,
"type" : " module " ,
"main" : " dist/cjs/index.cjs " ,
"exports" : {
"." : {
"import" : " ./dist/esm/index.js " ,
"require" : " ./dist/cjs/index.cjs "
},
"./subpath" : {
"import" : " ./dist/esm/subpath.js " ,
"require" : " ./dist/cjs/subpath.cjs "
}
}
}
dann sollte die DefinitelyTyped package.json
etwa so aussehen:
{
"name" : "@types/my-package" ,
"version" : "1.0.9999" ,
"type" : "module" ,
"types" : "index.d.ts" ,
"exports" : {
"." : {
"import" : "./index.d.ts" ,
"require" : "./index.d.cts"
} ,
"./subpath" : {
"import" : "./subpath.d.ts" ,
"require" : "./subpath.d.cts"
}
}
}
Beachten Sie, dass jeder exports
Unterpfad reflektiert wird und jede JavaScript-Datei eine entsprechende Deklarationsdatei mit einer passenden Dateierweiterung hat – eine .d.ts
-Datei ist eine .js
Datei, keine .mjs
oder .cjs
Datei!
Wenn das Implementierungspaket module.exports = ...
verwendet, sollte das DefinitelyTyped-Paket export =
und nicht export default
verwenden. (Wenn module.exports
alternativ nur ein Objekt benannter Eigenschaften ist, kann das DefinitelyTyped-Paket eine Reihe benannter Exporte verwenden.) Das häufigste Hindernis bei der Behebung dieses Problems ist die Verwirrung darüber, wie Typen zusätzlich zum primären Export exportiert werden. Angenommen, diese Typen verwenden fälschlicherweise export default
:
export interface Options {
// ...
}
export default function doSomething ( options : Options ) : void ;
Das Ändern der export default
in export =
führt zu einem Fehler:
export interface Options {
// ...
}
declare function doSomething ( options : Options ) : void ;
export = doSomething ;
// ^^^^^^^^^^^^^^^^^
// Error: An export assignment cannot be used in a module with other exported elements.
Um dies zu beheben, verschieben Sie die Typen in einen Namespace mit demselben Namen wie die Funktion:
declare namespace doSomething {
export interface Options {
// ...
}
}
declare function doSomething ( options : doSomething . Options ) : void ;
export = doSomething ;
Wenn Sie Hilfe bei der Behebung eines Problems benötigen, fragen Sie bitte im DefinitelyTyped-Kanal auf dem TypeScript Community Discord-Server nach.
Wenn Sie Typisierungen für ein npm-Paket hinzufügen, erstellen Sie ein Verzeichnis mit demselben Namen. Wenn sich das Paket, für das Sie Typisierungen hinzufügen, nicht auf npm befindet, legen Sie "nonNpm": true
in package.json
fest und stellen Sie sicher, dass der von Ihnen gewählte Name nicht mit dem Namen eines Pakets auf npm in Konflikt steht. (Sie können npm info <my-package>
verwenden, um zu überprüfen, ob das Paket <my-package>
vorhanden ist.)
In seltenen Fällen kann nonNpm
auf "conflict"
gesetzt sein, was darauf hindeutet, dass es auf npm ein Paket mit demselben Namen gibt, die Typen jedoch absichtlich mit diesem Paket in Konflikt stehen. Dies kann für Pakete gelten, die eine Umgebung wie @types/node
definieren, oder für Dummy-Pakete wie aws-lambda
. Vermeiden Sie nach Möglichkeit die Verwendung "conflict"
.
<my-package>-tests.ts
Es sollte eine Datei <my-package>-tests.ts
vorhanden sein, die zusammen mit allen importierten *.ts
Dateien als Ihre Testdatei gilt. Wenn Sie im Ordner des Moduls keine Testdateien sehen, erstellen Sie eine <my-package>-tests.ts
. Diese Dateien werden verwendet, um die aus den *.d.ts
Dateien exportierte API zu validieren, die als @types/<my-package>
geliefert werden. Sie selbst versenden nicht.
Änderungen an den *.d.ts
-Dateien sollten eine entsprechende *.ts
-Dateiänderung beinhalten, die die verwendete API anzeigt, damit jemand nicht versehentlich den Code beschädigt, auf den Sie angewiesen sind. Beispiel: Diese Änderung an einer Funktion in einer .d.ts
Datei fügt einer Funktion einen neuen Parameter hinzu:
index.d.ts
:
- export function twoslash(body: string): string
+ export function twoslash(body: string, config?: { version: string }): string
<my-package>-tests.ts
:
import {twoslash} from "./"
// $ExpectType string
const result = twoslash("//")
+ // Handle options param
+ const resultWithOptions = twoslash("//", { version: "3.7" })
+ // When the param is incorrect
+ // @ts-expect-error
+ const resultWithOptions = twoslash("//", { })
Wenn Sie sich fragen, wo Sie mit dem Testcode beginnen sollen, sind die Beispiele in der README-Datei des Originalpakets ein guter Ausgangspunkt.
Sie können Ihre Änderungen mit npm test <package to test>
im Stammverzeichnis dieses Repos validieren, wobei geänderte Dateien berücksichtigt werden.
Verwenden Sie $ExpectType
, um zu bestätigen, dass ein Ausdruck von einem bestimmten Typ ist, und @ts-expect-error
um zu bestätigen, dass ein Kompilierungsfehler vorliegt. Beispiele:
// $ExpectType void
f ( 1 ) ;
// @ts-expect-error
f ( "one" ) ;
Weitere Einzelheiten finden Sie in der dtslint-Readme-Datei.
.eslintrc.json
Wenn aus irgendeinem Grund eine Lint-Regel deaktiviert werden muss, deaktivieren Sie sie für eine bestimmte Zeile:
// eslint-disable-next-line no-const-enum
const enum Const {
One ,
}
const enum Enum { // eslint-disable-line no-const-enum
Two ,
}
Sie können Regeln weiterhin mit einer .eslintrc.json deaktivieren, sollten dies jedoch nicht in neuen Paketen tun. Das Deaktivieren von Regeln für das gesamte Paket erschwert die Überprüfung.
tsconfig.json
tsconfig.json
sollten noImplicitAny
, noImplicitThis
, strictNullChecks
und strictFunctionTypes
auf true
gesetzt sein.
Sie können die tsconfig.json
bearbeiten, um neue Testdateien hinzuzufügen, "target": "es6"
(erforderlich für asynchrone Funktionen) hinzuzufügen, "lib"
hinzuzufügen oder die Compileroption "jsx"
hinzuzufügen.
esModuleInterop
/ allowSyntheticDefaultImports
TL;DR: esModuleInterop
allowSyntheticDefaultImports
sind in Ihrer tsconfig.json
nicht zulässig .
Mit diesen Optionen ist es möglich, einen Standardimport für einen CJS-Export zu schreiben und so die integrierte Interoperabilität zwischen CJS- und ES-Modulen in Node und einigen JS-Bundlern zu modellieren:
// component.d.ts declare class Component { } // CJS export, modeling `module.exports = Component` in JS export = Component ; // index.d.ts // ESM default import, only allowed under 'esModuleInterop' or 'allowSyntheticDefaultExports' import Component from "./component" ;Da die Gültigkeit des Imports in
index.d.ts
zur Kompilierungszeit von bestimmten Kompilierungseinstellungen abhängt, die Benutzer Ihrer Typen nicht erben, würde die Verwendung dieses Musters in DefinitelyTyped Benutzer dazu zwingen, ihre eigenen Kompilierungseinstellungen zu ändern, was möglicherweise falsch ist für ihre Laufzeit. Stattdessen müssen Sie einen CJS-Import für einen CJS-Export schreiben, um eine umfassende, konfigurationsunabhängige Kompatibilität sicherzustellen:// index.d.ts // CJS import, modeling `const Component = require("./component")` in JS import Component = require ( "./component" ) ;
package.json
Diese Datei ist erforderlich und sollte dieser Vorlage folgen:
{
"private" : true ,
"name" : "@types/PACKAGE-NAME" ,
"version" : "1.2.9999" ,
"projects" : [
"https://aframe.io/"
] ,
"dependencies" : {
"@types/DEPENDENCY-1" : "*" ,
"@types/DEPENDENCY-2" : "*"
} ,
"devDependencies" : {
"@types/PACKAGE-NAME" : "workspace:."
} ,
"owners" : [
{
"name" : "Your Name Here" ,
"githubUsername" : "ghost"
}
]
}
Eine package.json
gibt alle Abhängigkeiten an, einschließlich anderer @types
-Pakete.
Sie müssen Nicht- @types
-Abhängigkeiten zur Liste der zulässigen externen Abhängigkeiten hinzufügen. Pikaday ist ein gutes Beispiel. Diese Ergänzungen werden von einem Betreuer genehmigt, was uns die Möglichkeit gibt, sicherzustellen, dass @types
-Pakete nicht von bösartigen Paketen abhängig sind.
Wenn das Implementierungspaket ESM verwendet und "type": "module"
angibt, sollten Sie package.json so ändern, dass es mit Folgendem übereinstimmt:
{
"type" : " module "
}
Dies gilt auch, wenn das Implementierungspaket exports
in seiner package.json enthält.
Definitiv typisiert ermöglicht peerDependencies
in package.json
. Peer-Abhängigkeiten können dazu beitragen, Situationen zu verhindern, in denen ein Paketmanager unerwartet zu neue Versionen oder mehr als eine Version desselben Pakets installiert. Allerdings haben Peer-Abhängigkeiten auch Nachteile. Paketmanager unterscheiden sich in der Handhabung von Peer-Abhängigkeiten (z. B. installiert yarn
sie nicht automatisch, npm
erfordert --legacy-peer-deps
für Nichtübereinstimmungen). Daher erfordern PRs, die neue Peer-Abhängigkeiten einführen, die Genehmigung des Betreuers und sollten auf bestimmte Umstände beschränkt sein.
Im Allgemeinen sollten Typpakete nur dann eine Peer-Abhängigkeit haben, wenn das Upstream-Paket eine Peer-Abhängigkeit von demselben Paket (oder seinen Typen) hat. Beispielsweise kann ein DT-Paket für eine React-Komponente eine Peer-Abhängigkeit von @types/react@*
angeben, da der Verbraucher zunächst @types/react
installieren musste, um JSX verwenden zu können. Wenn der Verbraucher @types/react@16
in seinem Projekt installiert, aber eine neuere Version von @types/react
auf npm verfügbar ist, kann die Peer-Abhängigkeit dem Paketmanager dabei helfen, @types/react@16
anstelle dieser neueren Version auszuwählen. Ebenso hat chai-as-promised
eine Peer-Abhängigkeit von chai
, daher sollte @types/chai-as-promised
eine Peer-Abhängigkeit von @types/chai
haben.
Es gibt einige Fälle, in denen das Upstream-Paket keine Peer-Abhängigkeit vom Types-Paket aufweist, eine Peer-Abhängigkeit jedoch dennoch angemessen ist. Dies sind typischerweise Fälle, in denen das Upstream-Paket ein anderes Paket erweitert und davon ausgeht, dass es existiert. Es hätte also eine Peer-Abhängigkeit deklarieren sollen, wenn es ein anderes Paket erweitert, was aber nicht der Fall war. Beispielsweise erweitert chai-match-pattern
chai
, deklariert jedoch keine Peer-Abhängigkeit von chai
, sondern benötigt diese, um zu funktionieren. @types/chai-match-pattern
sollte eine Peer-Abhängigkeit von @types/chai
haben.
Wenn ein Paket aufgrund einer regulären Abhängigkeit im Upstream-Paket einfach Typen aus einem anderen Paket als Teil seiner API verfügbar macht, sollte es keine Peer-Abhängigkeit verwenden. express
hat beispielsweise qs
in seinen "dependencies"
. Wenn Benutzer express
installieren, müssen sie qs
nicht manuell installieren. Ebenso hat @types/express
@types/qs
in seinen "dependencies"
. Es wäre falsch, @types/qs
als Peer-Abhängigkeit von @types/express
zu deklarieren, da dies erfordern würde, dass einige nachgeschaltete Verbraucher @types/qs
manuell installieren müssten.
.npmignore
Diese Datei definiert, welche Dateien in jedes @types
-Paket aufgenommen werden sollen. Es muss eine bestimmte Form annehmen. Für Pakete mit nur einer Version im Repo:
*
! ** / * .d.ts
! ** / * .d.cts
! ** / * .d.mts
! ** / * .d. * .ts
Das heißt „alle Dateien ignorieren, aber keine Deklarationsdateien ignorieren“. Bei Paketen, die mehr als eine Version im Repo haben, sollte die „neueste“ Version (auf der obersten Ebene) etwa Folgendes enthalten:
*
! ** / * .d.ts
! ** / * .d.cts
! ** / * .d.mts
! ** / * .d. * .ts
/ v15 /
/ v16 /
/ v17 /
Dies ist dasselbe wie das vorherige .npmignore
, ignoriert jedoch jedes der versionierten untergeordneten Verzeichnisse.
CI schlägt fehl, wenn diese Datei den falschen Inhalt enthält und den beabsichtigten Wert bereitstellt. Unabhängig davon, was diese Datei enthält, veröffentlicht der Herausgeber nur Deklarationsdateien.
pnpm dprint fmt -- 'path/to/package/**/*.ts'
ausführen können..vscode/settings.template.json
(oder einem Äquivalent für andere Editoren), um beim Speichern mit der VS Code-dprint-Erweiterung zu formatierenfunction sum(nums: number[]): number
: Verwenden Sie ReadonlyArray
, wenn eine Funktion nicht in ihre Parameter schreibt.interface Foo { new(): Foo; }
: Dies definiert einen Typ von Objekten, die neu erstellt werden können. Sie möchten wahrscheinlich declare class Foo { constructor(); }
.const Class: { new(): IClass; }
: Verwenden Sie lieber eine Klassendeklaration class Class { constructor(); }
anstelle einer neu fähigen Konstante.getMeAT<T>(): T
: Wenn ein Typparameter nicht in den Typen von Parametern vorkommt, haben Sie nicht wirklich eine generische Funktion, sondern nur eine getarnte Typzusicherung. Verwenden Sie lieber eine Assertion vom Typ Real, z. B. getMeAT() as number
. Beispiel, bei dem ein Typparameter akzeptabel ist: function id<T>(value: T): T;
. Beispiel, wo es nicht akzeptabel ist: function parseJson<T>(json: string): T;
. Ausnahme: new Map<string, number>()
ist OK.Function
und Object
ist fast nie eine gute Idee. In 99 % der Fälle ist es möglich, einen spezifischeren Typ anzugeben. Beispiele sind (x: number) => number
für Funktionen und { x: number, y: number }
für Objekte. Wenn überhaupt keine Gewissheit über den Typ besteht, ist any
die richtige Wahl, nicht Object
. Wenn die einzige bekannte Tatsache über den Typ darin besteht, dass es sich um ein Objekt handelt, verwenden Sie den Typ object
und nicht Object
oder { [key: string]: any }
.var foo: string | any
: Wenn any
in einem Union-Typ verwendet wird, ist der resultierende Typ immer noch any
. Auch wenn der string
Teil dieser Typanmerkung nützlich erscheinen mag, bietet er tatsächlich keine zusätzliche Typprüfung im Vergleich zur einfachen Verwendung any
. Je nach Absicht könnten akzeptable Alternativen any
, string
oder string | object
sein string | object
.TL;DR:
.github/CODEOWNERS
nicht ändern, sondern immer die Liste der Eigentümer inpackage.json
ändern.
DT verfügt über das Konzept der „Definitionsbesitzer“, bei denen es sich um Personen handelt, die die Qualität der Typen eines bestimmten Moduls aufrechterhalten möchten.
Um sich selbst als Definitionseigentümer hinzuzufügen, ändern Sie das owners
in package.json
:
"owners" : [
{
"name" : " Some Person " ,
"githubUsername" : " somebody "
},
{
"name" : " Some Corp " ,
"url" : " https://example.org "
}
]
Beachten Sie, dass diese Liste nicht zur Anrechnung von Beiträgen dient; Es dient ausschließlich der Verwaltung von PR-Bewertungen.
Einmal pro Woche werden die Definitionseigentümer mit der Datei .github/CODEOWNERS synchronisiert, die unsere Quelle der Wahrheit ist.
Definitiv Typed ist eines der aktivsten Repositories auf GitHub. Sie haben sich vielleicht gefragt, wie das Projekt zustande kam. @johnnyreilly hat eine Geschichte von Definitely Typed geschrieben. Es erzählt die Geschichte der Anfänge von Definitely Typed, von einem von @borisyankov erstellten Repository bis zu dem Punkt, an dem es zu einem zentralen Bestandteil des TypeScript-Ökosystems wurde. Die Geschichte von Definitely Typed können Sie hier lesen.
@types
-Paketen auf npm? Der master
Zweig wird dank DefinitelyTyped-tools automatisch im @types
-Bereich auf npm veröffentlicht.
Es kommt darauf an, aber die meisten Pull-Anfragen werden innerhalb einer Woche zusammengeführt. Einige PRs können von den Eigentümern eines Moduls zusammengeführt werden, und zwar viel schneller. Rund:
PRs, die nur die Typen eines Moduls ändern und entsprechende Teständerungen haben, werden viel schneller zusammengeführt
PRs, die von einem in der package.json
der Definition aufgeführten Eigentümer genehmigt wurden, werden normalerweise schneller zusammengeführt; PRs für neue Definitionen werden mehr Zeit in Anspruch nehmen, da sie eine stärkere Überprüfung durch die Betreuer erfordern. Jede PR wird vor der Zusammenführung von einem TypeScript- oder Definitely Typed-Teammitglied überprüft. Bitte haben Sie etwas Geduld, da menschliche Faktoren zu Verzögerungen führen können. Sehen Sie sich das New Pull Request Status Board an, um den Fortschritt zu sehen, während Betreuer die offenen PRs durcharbeiten.
Für Änderungen an sehr beliebten Modulen, z. B. Node/Express/Jest, die jede Woche viele Millionen Downloads auf npm haben, sind die Anforderungen an Beiträge etwas höher. Änderungen an diesen Projekten können massive Auswirkungen auf das Ökosystem haben, daher gehen wir mit Änderungen an ihnen mit großer Sorgfalt um. Diese Module erfordern sowohl eine Genehmigung durch einen DT-Betreuer als auch begeisterte Unterstützung durch die Modulbesitzer. Die Hürde, dies zu bestehen, kann ziemlich hoch sein und PRs können oft langweilig werden, weil es keinen Champion gibt. Wenn Sie feststellen, dass sich niemand verpflichtet, versuchen Sie, Ihre PR weniger stark in den Fokus zu rücken.
@types
npm-Paket aktualisiert?NPM-Pakete sollten innerhalb einer Stunde aktualisiert werden. Wenn mehr als eine Stunde vergangen ist, erwähnen Sie die PR-Nummer im Definitely Typed-Kanal auf dem TypeScript Community Discord-Server und der aktuelle Betreuer wird das richtige Teammitglied zur Untersuchung beauftragen.
<reference types="" />
oder einen Import verwenden? Wenn das Modul, auf das Sie verweisen, ein Modul ist ( export
verwendet), verwenden Sie einen Import. Wenn das Modul, auf das Sie verweisen, ein Ambient-Modul ist ( declare module
verwendet) oder nur Globals deklariert, verwenden Sie <reference types="" />
.
tsconfig.json
, in der "noImplicitAny": true
, "noImplicitThis": true
oder "strictNullChecks": true
fehlt.Dann liegen sie falsch und wir haben es noch nicht bemerkt. Sie können helfen, indem Sie eine Pull-Anfrage senden, um die Probleme zu beheben.
Ja, mit dprint. Wir empfehlen die Verwendung einer dprint-Erweiterung für Ihren Editor.
Alternativ können Sie einen Git-Hook aktivieren, der Ihren Code automatisch formatiert. Führen Sie pnpm run setup-hooks
aus. Wenn Sie dann einen Commit durchführen, wird der Befehl dprint fmt
für geänderte Dateien ausgeführt. Wenn Sie die Vorteile des teilweisen Klonens nutzen, rufen Sie unbedingt git sparse-checkout add .husky
auf, um die Git-Hooks auszuchecken, bevor Sie das setup-hooks
-Skript ausführen.
Für die Zusammenführung von Pull-Anfragen ist keine korrekte Formatierung erforderlich. Jeder unformatierte Code wird nach dem Zusammenführen automatisch neu formatiert.
Wenn Sie ein VS Code-Benutzer sind, empfehlen wir, die Datei
.vscode/settings.template.json
nach.vscode/settings.json
zu kopieren. Diese Vorlage legt die dprint VS Code-Erweiterung als Standardformatierer im Repository fest.
Hier sind die aktuell angeforderten Definitionen.
Wenn Typen Teil eines Webstandards sind, sollten sie zum TypeScript-DOM-lib-generator beigetragen werden, damit sie Teil des Standard lib.dom.d.ts
werden können.
Wenn überhaupt kein Quell-JavaScript-Code vorhanden ist, beispielsweise wenn Sie Hilfstypen oder Typen für eine Spezifikation schreiben, sollten Sie die Typen selbst veröffentlichen und nicht auf Definitely Typed. Da sie dazu gedacht sind, Typen für vorhandenen JavaScript-Code bereitzustellen, sind @types
Pakete nicht für den direkten Import gedacht. Das heißt, Sie sollten kein Definitely Typed-Paket erstellen, das wie import type { ... } from "@types/foo"
verwendet werden soll. Sie sollten auch nicht damit rechnen, import type { ... } from "foo"
zu schreiben, wenn kein foo
installiert ist.
Dies unterscheidet sich von der Bereitstellung von Typen für eine reine Browser-JavaScript-Bibliothek oder von Typen für eine gesamte Umgebung wie Node, Bun usw. Dort werden die Typen entweder implizit oder mittels /// <references types="foo" />
aufgelöst.
Einige Pakete, wie chai-http, exportieren eine Funktion.
Importieren dieses Moduls mit einem Import im ES6-Stil in der Form import * as foo from "foo";
führt zu dem Fehler:
Fehler TS2497: Modul „foo“ wird in eine Nicht-Modul-Entität aufgelöst und kann mit diesem Konstrukt nicht importiert werden.
Dieser Fehler kann unterdrückt werden, indem die Funktionsdeklaration mit einem leeren Namespace mit demselben Namen zusammengeführt wird. Von dieser Vorgehensweise wird jedoch abgeraten. Dies ist eine häufig zitierte Stack Overflow-Antwort zu diesem Thema.
Es ist sinnvoller, das Modul mit import foo = require("foo");
Syntax. Wenn Sie jedoch einen Standardimport wie import foo from "foo";
Sie haben zwei Möglichkeiten:
--allowSyntheticDefaultImports
verwenden, wenn Ihre Modullaufzeit ein Interop-Schema für Nicht-ECMAScript-Module unterstützt, d. h. wenn Standardimporte in Ihrer Umgebung funktionieren (z. B. Webpack, SystemJS, ESM).--esModuleInterop
verwenden, wenn TypeScript sich um Nicht-ECMAScript-Interop kümmern soll (seit TypeScript 2.7). export =
, aber ich bevorzuge die Verwendung von Standardimporten. Kann ich export =
in export default
ändern? Wie in der vorherigen Frage beziehen Sie sich auf die Verwendung der Compileroptionen --allowSyntheticDefaultImports
oder --esModuleInterop
.
Ändern Sie die Typdefinition nicht, wenn sie korrekt ist. Für ein npm-Paket ist export =
korrekt, wenn node -p 'require("foo")'
zum Importieren eines Moduls funktioniert, und export default
ist korrekt, wenn node -p 'require("foo").default'
zum Importieren eines Moduls funktioniert .
Dann haben Sie die unterstützte Mindestversion festgelegt, indem Sie "minimumTypeScriptVersion": "XY"
in package.json
angeben.
Wenn Ihr Projekt jedoch Typen verwalten muss, die beispielsweise mit 3.7 und höher kompatibel sind , und gleichzeitig Typen, die mit 3.6 oder niedriger kompatibel sind, müssen Sie die Funktion typesVersions
verwenden. Eine ausführliche Erläuterung dieser Funktion finden Sie in der offiziellen TypeScript-Dokumentation.
Hier ist ein kurzes Beispiel, um Ihnen den Einstieg zu erleichtern:
Sie müssen typesVersions
zu package.json
hinzufügen:
{
"private" : true ,
"types" : " index " ,
"typesVersions" : {
"<=3.6" : { "*" : [ " ts3.6/* " ] }
}
}
Erstellen Sie das im Feld typesVersions
erwähnte Unterverzeichnis in Ihrem Typenverzeichnis (in diesem Beispiel ts3.6/
“). ts3.6/
unterstützt TypeScript-Versionen 3.6 und niedriger, kopieren Sie also die vorhandenen Typen und Tests dorthin.
Fügen Sie im Stammverzeichnis des Pakets die TypeScript 3.7-Funktionen hinzu, die Sie verwenden möchten. Wenn Benutzer das Paket installieren, beginnen TypeScript 3.6 und niedriger mit ts3.6/index.d.ts
, während TypeScript 3.7 und höher mit index.d.ts
beginnen.
Sie können sich als Beispiel Bluebird ansehen.
Dies könnte zum TypeScript-DOM-lib-generator gehören. Sehen Sie sich dort die Richtlinien an. Wenn der Standard noch ein Entwurf ist, gehört er hierher. Verwenden Sie einen Namen, der mit dom-
beginnt, und fügen Sie einen Link zum Standard als „Projekt“-Link in package.json
ein. Wenn es den Entwurfsmodus verlässt, entfernen wir es möglicherweise aus Definitely Typed und verwerfen das zugehörige @types
-Paket.
HINWEIS: Die Diskussion in diesem Abschnitt geht davon aus, dass Sie mit der semantischen Versionierung vertraut sind
Jedes Definitely Typed-Paket wird bei der Veröffentlichung in npm versioniert. Die DefinitelyTyped-tools (das Tool, das @types
-Pakete in npm veröffentlicht) legen die Version des Deklarationspakets mithilfe der in package.json
aufgeführten Versionsnummer major.minor.9999
fest. Hier sind zum Beispiel die ersten Zeilen der Typdeklarationen von Node für Version 20.8.x
zum Zeitpunkt des Schreibens:
{
"private" : true ,
"name" : " @types/node " ,
"version" : " 20.8.9999 "
}
Da die Version als 20.8.9999
aufgeführt ist, lautet die npm-Version des @types/node
-Pakets ebenfalls 20.8.x
Beachten Sie, dass die Version in package.json
nur die Version major.minor
(z. B. 10.12
) gefolgt von .9999
enthalten sollte. Dies liegt daran, dass nur die Haupt- und Nebenversionsnummern zwischen Bibliothekspaketen und Typdeklarationspaketen abgeglichen werden. (Die .9999
soll sicherstellen, dass lokale @types
Pakete während der lokalen Entwicklung immer auf dem neuesten Stand sind.) Die Patch-Release-Nummer des Typdeklarationspakets (z. B. .0
in 20.8.0
) wird von Definitely Typed auf Null initialisiert und jedes Mal erhöht Für dieselbe Haupt-/Nebenversion der entsprechenden Bibliothek wird ein neues @types/node
-Paket auf npm veröffentlicht.
Manchmal können Typdeklarationspaketversionen und Bibliothekspaketversionen nicht mehr synchron sein. Im Folgenden finden Sie einige häufige Gründe dafür, in der Reihenfolge, in der sie den Nutzern einer Bibliothek Unannehmlichkeiten bereiten. Nur der letzte Fall ist typischerweise problematisch.
@types
-Paketen übereinstimmen, sollte npm update
normalerweise funktionieren. ❗ Wenn Sie Typdeklarationen für eine Bibliothek aktualisieren, legen Sie die major.minor
Nebenversion in package.json
immer so fest, dass sie mit der Bibliotheksversion übereinstimmt, die Sie dokumentieren! ❗
Die semantische Versionierung erfordert, dass Versionen mit Breaking Changes die Hauptversionsnummer erhöhen müssen. Beispielsweise muss eine Bibliothek, die eine öffentlich exportierte Funktion nach ihrer Veröffentlichung 3.5.8
entfernt, ihre Version in ihrer nächsten Version auf 4.0.0
erhöhen. Darüber hinaus sollte, wenn die Version 4.0.0
der Bibliothek erscheint, auch das Definitely Typed-Typdeklarationspaket auf 4.0.0
aktualisiert werden, einschließlich aller wichtigen Änderungen an der API der Bibliothek.
Viele Bibliotheken verfügen über eine große installierte Basis von Entwicklern (einschließlich Betreuern anderer Pakete, die diese Bibliothek als Abhängigkeit verwenden), die nicht sofort auf eine neue Version mit wichtigen Änderungen umsteigen, da es Monate dauern kann, bis ein Betreuer Zeit zum Umschreiben hat Code zur Anpassung an die neue Version. In der Zwischenzeit möchten Benutzer alter Bibliotheksversionen möglicherweise weiterhin Typdeklarationen für ältere Versionen aktualisieren.
Wenn Sie beabsichtigen, weiterhin die ältere Version der Typdeklarationen einer Bibliothek zu aktualisieren, können Sie einen neuen Unterordner (z. B. /v2/
) erstellen, der nach der aktuellen (bald „alten“) Version benannt ist, und vorhandene Dateien aus der aktuellen Version dorthin kopieren .
Stellen Sie beim Erstellen eines neuen Versionsordners sicher, dass das Versionsfeld von package.json
aktualisiert wurde. pnpm
wird bei Bedarf automatisch in dieses versionierte Paket aufgelöst. Wenn andere Pakete im Repo von dieser neuen Version abhängig sein müssen, stellen Sie sicher, dass auch ihre package.json
s aktualisiert werden.
Wenn wir beispielsweise types/history/v2
erstellen, würde dessen package.json
wie folgt aussehen:
{
"private" : true ,
"name" : " @types/history " ,
"version" : " 2.4.9999 "
}
Ein anderes Paket kann diese Version auswählen, indem es Folgendes angibt:
{
"private" : true ,
"name" : " @types/browser-sync " ,
"version" : " 2.26.9999 " ,
"dependencies" : {
"@types/history" : " ^2 "
}
}
Außerdem funktioniert /// <reference types=".." />
nicht mit der Pfadzuordnung, daher müssen Abhängigkeiten import
verwenden.
@types
-Pakete geben immer Pakete derselben Version ein, daher stehen @types/[email protected]
für [email protected]
. Infolgedessen werden alle Änderungen, ob bahnbrechend oder nicht, als Patch-Revisionen veröffentlicht, es sei denn, sie sind mit einer größeren/kleineren Änderung gepaart, um die Zielpaketversion zu ändern (zufällig oder nicht).
Wenn es um Breaking Changes geht, berücksichtigen DT-Betreuer die Beliebtheit des Pakets, die Vorteile des vorgeschlagenen Breaking Change, den Aufwand, der für Benutzer erforderlich ist, um ihren Code zu reparieren, und ob die Änderung sinnvollerweise verzögert werden könnte, bis sie synchronisiert werden kann mit einer großen Beeinträchtigung der Upstream-Bibliothek.
Das TypeScript-Handbuch enthält hervorragende allgemeine Informationen zum Schreiben von Definitionen und auch diese Beispieldefinitionsdatei, die zeigt, wie man eine Definition mit der Modulsyntax im ES6-Stil erstellt und gleichzeitig Objekte spezifiziert, die dem globalen Bereich zur Verfügung gestellt werden. Diese Technik wird praktisch in der Definition für big.js
demonstriert, einer Bibliothek, die global per Skript-Tag auf einer Webseite geladen oder über require oder Importe im ES6-Stil importiert werden kann.
Um zu testen, wie Ihre Definition sowohl bei globaler Referenzierung als auch als importiertes Modul verwendet werden kann, erstellen Sie einen test
und legen Sie dort zwei Testdateien ab. Nennen Sie einen YourLibraryName-global.test.ts
und den anderen YourLibraryName-module.test.ts
. Die globale Testdatei sollte die Definition entsprechend der Verwendung in einem Skript ausführen, das auf einer Webseite geladen wird, auf der die Bibliothek im globalen Bereich verfügbar ist. In diesem Szenario sollten Sie keine Importanweisung angeben. Die Modul -Testdatei sollte die Definition entsprechend der Art und Weise ausüben, wie sie beim Importieren verwendet werden würde (einschließlich der import
-Anweisung (en)). Wenn Sie eine files
in Ihrer Datei tsconfig.json
angeben, sollten Sie beide Testdateien einfügen. Ein praktisches Beispiel hierfür ist auch in der big.js
-Definition verfügbar.
Bitte beachten Sie, dass es nicht erforderlich ist, die Definition in jeder Testdatei vollständig auszuüben. Es ist ausreichend, nur die global zugänglichen Elemente in der globalen Testdatei zu testen und die Definition in der Modul -Testdatei vollständig auszuüben oder umgekehrt.
Typen für ein Scoped -Paket @foo/bar
sollten in types/foo__bar
gehen. Beachten Sie den doppelten Unterstrich.
Dieses Projekt ist unter der MIT-Lizenz lizenziert.
Urheberrechte in den Definitionsdateien sind jedes zu Beginn jeder Definitionsdatei aufgeführten Mitwirkenden entsprechen.