Le référentiel des définitions de type TypeScript de haute qualité.
Vous pouvez également lire ce README en Español, 한국어, Русский, 简体中文, Português, Italiano, 日本語 et English!
Lien vers le Manuel de l'administrateur
Definitely Typed est récemment passé sur un véritable monorepo pnpm
; vous voudriez peut-être relire ce document pour connaître les changements apportés à la structure des packages dans ce dépôt.
Au minimum, vous voudriez peut-être faire un git clean -fdx
sur le dépôt (ou node ./scripts/clean-node-modules.js
sur Windows) pour nettoyer node_modules
et exécuter pnpm install --filter .
pour installer la racine du workspace. Voir les sections suivantes pour plus d'informations sur pnpm install
.
Cette section permet de suivre l'état de santé du référentiel et du processus de publication. Elle peut être utile aux contributeurs qui rencontrent des problèmes avec leurs PR et leurs packages.
- Dernière version type-checked/linted proprement :
- Tous les packages passent la vérification des types et du linter :
- Tous les packages ont été publié sur npm en moins d'une heure et demie :
- typescript-bot a été actif sur Definitely Typed
- Mise à jour de l'état de l'infrastructure actuel
Si quelque chose semble incorrect ou si l'un des éléments ci-dessus échoue, merci de nous le faire savoir dans le canal Definitely Typed sur le serveur Discord de la Communauté TypeScript.
Voir le Manuel TypeScript.
C'est la méthode privilégiée. Par exemple :
npm install --save-dev @types/node
Pour installer des types d'un module scopé, remplacez le @
par deux underscore après le scope. Par exemple, pour installer des types pour @babel/preset-env
:
npm install --save-dev @types/babel__preset-env
Les types devraient alors être automatiquement inclus par le compilateur.
Vous pourriez avoir besoin d'ajouter une référence types
si vous n'utilisez pas de modules :
/// <reference types="node" />
Plus d'informations dans le manuel.
Pour un package npm "foo", les types pour celui-ci seront dans "@types/foo".
Si votre package spécifie des types avec la clé types
ou typings
dans son package.json
, le registre npm affichera que le package a des bindings disponibles comme ceci :
Si vous ne trouvez toujours pas les types, recherchez simplement les fichiers ".d.ts" dans le package et incluez-les manuellement avec /// <reference path="" />
.
Definitely Typed ne teste que les packages sur des versions de TypeScript datant de moins de 2 ans.
Anciennes versions de TypeScript
Les packages @types
ont des tags pour les versions de TypeScript qu'ils supportent explicitement, de sorte que vous pouvez généralement obtenir des versions plus anciennes des packages qui précèdent la fenêtre de 2 ans.
Par exemple, si vous lancez npm dist-tags @types/react
, vous verrez que TypeScript 2.5 peut utiliser les types pour react@16.0, alors que TypeScript 2.6 et 2.7 peuvent utiliser les types pour react@16.4 :
Tag | Version |
---|---|
latest | 16.9.23 |
ts2.0 | 15.0.1 |
... | ... |
ts2.5 | 16.0.36 |
ts2.6 | 16.4.7 |
ts2.7 | 16.4.7 |
... | ... |
- Télécharger manuellement depuis la branche
master
de ce dépôt et les placer dans votre projet Typings(utilisez les alternatives préférées, typings est déprécié)NuGet(utilisez les alternatives préférées, la publication des types DT de Nuget a été désactivée)
Vous pourriez avoir besoin d'ajouter le manuel references.
Definitely Typed ne fonctionne que grâce aux contributions d'utilisateurs comme vous !
Avant de partager votre amélioration avec le monde, utilisez les types vous-même en créant un fichier typename.d.ts
dans votre projet et en remplissant ses exports :
declare module "libname" {
// Types à l'intérieur ici
export function helloWorldMessage(): string;
}
Vous pouvez éditer les types directement dans node_modules/@types/foo/index.d.ts
pour valider vos changements, puis apporter les changements à ce repo avec les étapes ci-dessous.
Alternativement, vous pouvez utiliser module augmentation pour étendre les types existants du module DT ou utiliser la technique declare module
ci-dessus qui remplacera la version dans node_modules
.
Ajoutez-le à votre tsconfig.json
:
"baseUrl": "types",
"typeRoots": ["types"],
Créez types/foo/index.d.ts
contenant les déclarations pour le module "foo".
Vous devriez maintenant être capable d'importer "foo"
dans votre code et il sera dirigé vers la nouvelle définition de type.
Ensuite, compilez et exécutez le code pour vous assurer que votre définition de type correspond bien à ce qui se passe à l'exécution.
Une fois que vous avez testé vos définitions avec du code réel, faites une PR puis suivez les instructions pour modifier un package existant ou créer un nouveau package.
Une fois que vous avez testé votre package, vous pouvez le partager sur Definitely Typed.
Tout d'abord, forkez ce dépôt, clonez le,
installez node, et lancez npm install
. Notez que pnpm install
installera l'intégralité
du dépôt, y compris des packages que vous ne modifiez peut-être pas. Si vous souhaitez installer uniquement un sous-ensemble,
vous pouvez lancer pnpm install -w --filter "{./types/foo}..."
pour installer @types/foo
et
toutes ses dépendances. Si vous avez besoin de lancer des tests de packages qui dépendent de @types/foo
, vous pouvez lancer pnpm install -w --filter "...{./types/foo}..."
pour récupérer tous les packages associés nécessaires aux tests.
Note
Si vous utilisez Windows, vous constaterez peut-être que git clean
ne supprime pas le répertoire node_modules
ou se bloque lors de cette opération. Si vous devez supprimer node_modules
, vous pouvez lancer pnpm clean-node-modules
pour réinitialiser le dépôt.
Nous utilisons un bot pour permettre à un grand nombre de pull requests de DefinitelyTyped d'être traitées entièrement en libre-service. Vous pouvez en savoir plus sur pourquoi et comment ici. Voici une référence pratique montrant le cycle de vie de pull request à DT :
Vous pouvez cloner l'ensemble du dépôt comme d'habitude, mais il est volumineux et comprend un énorme répertoire de packages de type.
Vous pouvez cloner l'ensemble du dépôt comme d'habitude, mais il est volumineux et comprend un énorme répertoire de packages de type. Cela prendra du temps à cloner et peut s'avérer inutilement lourd.
Pour un clone plus facile à gérer qui inclut seulement les packages de type qui vous concernent, vous pouvez utiliser les fonctionnalités de git sparse-checkout
, --filter
, et --depth
. Cela réduira le temps de clonage et améliorera les performances de git.
⚠️ Ceci nécessite au minimum git version 2.27.0, qui est probablement plus récent que la version par défaut sur la plupart des machines. Des procédures plus complexes sont disponibles dans les versions plus anciennes, mais ne sont pas couvertes par ce guide.
git clone --sparse --filter=blob:none <forkedUrl>
--sparse
initialise le fichier sparse-checkout afin que le répertoire de travail ne contienne au départ que les fichiers situés à la racine du référentiel.--filter=blob:none
exclura des fichiers, les récupérant uniquement en cas de besoin.
git sparse-checkout add types/<type> types/<dependency-type> ...
- Apporter des modifications. N'oubliez pas d'éditer les tests. Si vous apportez des modifications radicales, n'oubliez pas de mettre à jour la version majeure.
- Run
npm test <package-à-tester>
.
Quand vous faites une PR pour éditer un package existant, dt-bot
devrait @-mentionner les auteurs du package.
S'il ne le fait pas, vous pouvez le faire vous-même dans un commentaire associé à la PR.
Si vous êtes l'auteur de la lib et que votre package est écrit en TypeScript, regroupez les fichiers de déclaration autogénérés dans votre package au lieu de le publier sur Definitely Typed. Vous pouvez également générer des fichiers de déclaration à partir de fichiers JavaScript, en utilisant JSDoc pour les annotations de type.
Si vous ajoutez des typages pour un package npm, créez un répertoire avec le même nom.
Si le package pour lequel vous ajoutez des typages n'est pas sur npm, assurez-vous que le nom que vous choisissez pour lui n'entre pas en conflit avec le nom d'un package sur npm.
(Vous pouvez utiliser npm info <mon-package>
pour vérifier l'existence du package <mon-package>
).
Votre package doit avoir cette structure :
Fichier | Objectif |
---|---|
index.d.ts |
Il contient les typages du package. |
<mon-package>-tests.ts |
Il contient un exemple de code qui teste les typages. Ce code ne s'exécute pas, mais il est vérifié. |
tsconfig.json |
Cela vous permet d'exécuter tsc à l'intérieur du package. |
.eslintrc.json |
(Rarement) Nécessaire uniquement pour désactiver les règles de lint écrites pour eslint. |
package.json |
Contient les métadonnées du package, y compris son nom, sa version et ses dépendances. |
.npmignore |
Spécifie quels fichiers doivent être inclus dans le package. |
Vous pouvez les générer en lançant npx dts-gen --dt --name <mon-package> --template module
.
Voir toutes les options sur dts-gen.
Si vous avez des fichiers .d.ts
en plus de index.d.ts
, assurez-vous qu'ils sont référencés soit dans index.d.ts
soit dans les tests.
Les membres de Definitely Typed surveillent régulièrement les nouveaux PRs, bien qu'il faille garder à l'esprit que le nombre d'autres PRs peut ralentir les choses.
Pour un bon exemple de package, voir base64-js.
Lorsqu'un package bundles à ses propres types, les types doivent être supprimés de Definitely Typed pour éviter toute confusion.
Vous pouvez le supprimer en lançant npm run not-needed -- <nomDuPackage> <commeVersion> [<nomDeLaLib>]
.
<nomDuPackage>
: C'est le nom du répertoire à supprimer.<commeVersion>
: Un stub sera publié dans@types/<nomDuPackage>
avec cette version. Elle doit être supérieure à toute version actuellement publiée, et doit être une version de<nomDeLaLib>
sur npm.<nomDeLaLib>
: Nom du package npm qui remplace les types de Definitely Typed. Habituellement, il est identique à<nomDuPackage>
, dans ce cas vous pouvez l'omettre.
Si un package n'a jamais été sur Definitely Typed, il n'a pas besoin d'être ajouté à notNeededPackages.json
.
Testez vos modifications en lançant npm test <package à tester>
où <package à tester>
est le nom de votre package.
Vous devez l'exécuter depuis le répertoire DefinitelyTyped car les package.json
individuels ne définissent pas de scripts de test.
Ce script utilise dtslint pour lancer le compilateur TypeScript sur vos fichiers dts.
Une fois que tous vos changements sont prêts, lancez npm run test-all
pour voir comment vos changements affectent les autres modules.
dtslint inclut des vérifications de format de module et de configuration package.json
à partir de @arethetypeswrong/cli. Les vérifications ne s'exécutent que si un package d'implémentation compatible avec SemVer-major peut être trouvé sur npm pour être comparé au package DefinitelyTyped. (Les packages DefinitelyTyped marqués comme nonNpm
dans leur package.json
sont ignorés.)
De nombreux packages échouent actuellement aux vérifications attw
et doivent être corrigés. Pour nous permettre de progresser de manière incrémentale, les vérifications attw
échouées ne font pas échouer l'exécution de dtslint
lorsque le package est listé dans failingPackages
dans attw.json
, mais elles seront toujours signalées dans la sortie de pnpm test my-package
. Si vous corrigez le package, retirez-le de failingPackages
afin que les vérifications attw
puissent commencer à faire échouer les exécutions de dtslint
.
Tous les problèmes signalés par attw
ont une documentation liée dans la sortie. Voici quelques règles générales pour éviter les problèmes :
-
Le
package.json
dans le package DefinitelyTyped doit avoir des champstype
etexports
correspondants si le package d'implémentation les utilise dans sonpackage.json
. Par exemple, si unpackage.json
d'implémentation ressemble à :{ "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" } } }
alors le
package.json
dans DefinitelyTyped devrait ressembler à ceci :{ "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" } } }
Notez que chaque sous-chemin
exports
est reflété, et chaque fichier JavaScript a un fichier de déclaration correspondant avec une extension de fichier correspondante à un fichier.d.ts
d'un fichier.js
, et non un fichier.mjs
ou.cjs
! -
Lorsque le package d'implémentation utilise
module.exports = ...
, le package DefinitelyTyped doit utiliserexport =
, et nonexport default
. (Alternativement, si lemodule.exports
est juste un objet de propriétés nommées, le package DefinitelyTyped peut utiliser une série d'exports nommés.) L'obstacle le plus courant pour corriger ce problème est la confusion sur la façon d'exporter des types en plus de l'exportation principale. Par exemple, supposons que ces types utilisent incorrectementexport default
:export interface Options { // ... } export default function doSomething(options: Options): void;
Changer
export default
enexport =
crée une erreur :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.
Pour résoudre cela, déplacez les types à l'intérieur d'un namespace portant le même nom que la fonction :
declare namespace doSomething { export interface Options { // ... } } declare function doSomething(options: doSomething.Options): void; export = doSomething;
Si vous avez besoin d'aide pour résoudre un problème, veuillez demander dans le canal DefinitelyTyped sur le serveur Discord de la communauté TypeScript.
Si vous ajoutez des types pour un package npm, créez un répertoire portant le même nom.
Si le package pour lequel vous ajoutez des types n'est pas sur npm, assurez-vous que le nom que vous choisissez pour lui n'entre pas en conflit avec le nom d'un package sur npm.
(Vous pouvez utiliser npm info <mon-package>
pour vérifier l'existence du package <mon-package>
).
Dans de rares occasions, nonNpm
peut être défini sur "conflict"
, ce qui indique qu'il existe un package sur npm avec le même nom, mais que les types sont intentionnellement en conflit avec ce package.
Cela peut être vrai pour les packages qui définissent un environnement comme @types/node
ou pour des packages factices comme aws-lambda
. Évitez d'utiliser "conflict"
autant que possible.
Il devrait y avoir un fichier <mon-package>-tests.ts
, qui est considéré comme votre fichier de test, avec tous les fichiers *.ts
qu'il importe.
Si vous ne voyez aucun fichier de test dans le dossier du module, créez un fichier <mon-package>-tests.ts
.
Ces fichiers sont utilisés pour valider l'API exportée depuis les fichiers *.d.ts
qui sont livrés en tant que @types/<mon-package>
.
Ils ne sont pas eux-mêmes expédiés.
Les changements apportés aux fichiers *.d.ts
doivent inclure un changement correspondant au fichier *.ts
qui montre l'API utilisée, afin que quelqu'un ne casse pas accidentellement le code dont vous dépendez.
Par exemple, cette modification d'une fonction dans un fichier .d.ts
ajoute un nouveau paramètre à une fonction :
index.d.ts
:
- export function twoslash(body: string): string
+ export function twoslash(body: string, config?: { version: string }): string
<mon-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("//", { })
Si vous vous demandez par où commencer avec le code de test, les exemples dans le README du module sont un bon point de départ.
Vous pouvez valider vos changements avec npm test <package à tester>
depuis la racine de ce repo, qui prend en compte les fichiers modifiés.
Utilisez $ExpectType
pour affirmer qu'une expression est d'un type donné, et @ts-expect-error
pour affirmer qu'il s'agit d'une erreur de compilation. Exemples :
// $ExpectType void
f(1);
// @ts-expect-error
f("one");
Pour plus de détails, voir le readme de dtslint.
Si, pour une raison quelconque, une règle de lint doit être désactivée, désactivez-la pour une ligne spécifique :
// eslint-disable-next-line no-const-enum
const enum Const {
One,
}
const enum Enum { // eslint-disable-line no-const-enum
Two,
}
Vous pouvez toujours désactiver les règles avec un fichier .eslintrc.json
, mais vous ne devriez pas le faire dans les nouveaux packages.
Désactiver les règles pour l'ensemble du package rend la révision plus difficile.
tsconfig.json
doit avoir noImplicitAny
, noImplicitThis
, strictNullChecks
, et strictFunctionTypes
défini à true
.
Vous pouvez éditer le fichier tsconfig.json
pour ajouter de nouveaux fichiers de test, pour ajouter "target" : "es6"
(nécessaire pour les fonctions asynchrones), pour ajouter à "lib"
, ou pour ajouter l'option de compilateur "jsx"
.
TL;DR : esModuleInterop
et allowSyntheticDefaultImports
ne sont pas autorisés dans votre tsconfig.json
.
Ces options permettent d'écrire une importation par défaut pour une exportation CJS, modélisant l'interopérabilité intégrée entre les modules CJS et ES dans Node et dans certains bundlers JS:
// 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";Puisque la validité à la compilation de l'import dans
index.d.ts
dépend de paramètres de compilation spécifiques, dont les utilisateurs de vos types n'héritent pas, l'utilisation de ce pattern dans DefinitelyTyped forcerait les utilisateurs à changer leurs propres paramètres de compilation, ce qui pourrait être incorrect pour leur environnement d'exécution. Au lieu de cela, vous devez écrire un import CJS pour un export CJS afin d'assurer une compatibilité généralisée et indépendante de la configuration :// index.d.ts // CJS import, modeling `const Component = require("./component")` in JS import Component = require("./component");
Ce fichier est requis et doit suivre ce modèle :
{
"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"
}
]
}
Un package.json
spécifie toutes les dépendances, y compris les autres packages @types
.
Vous devez ajouter les dépendances non-@types
à la liste des dépendances externes autorisées.
Pikaday est un bon exemple.
Ces ajouts sont approuvés par un mainteneur, ce qui nous donne l'occasion de nous assurer que les packages @types
ne dépendent pas de packages malveillants.
Si le package d'implémentation utilise ESM et spécifie "type" : "module"
, alors vous devez ajouter un package.json avec la même chose :
{
"type": "module"
}
Ceci s'applique également si le package d'implémentation a exports
dans son package.json.
Definitely Typed autorise les peerDependencies
dans package.json
.
Les peer dependencies peuvent aider à prévenir les situations où un gestionnaire de package installe de manière inattendue des versions trop récentes ou plusieurs versions du même package.
Cependant, les peer dependencies ont des inconvénients ; les gestionnaires de packages diffèrent dans leur gestion des peer dependencies (par exemple, yarn
ne les installe pas automatiquement, npm
nécessite --legacy-peer-deps
pour les incompatibilités).
Ainsi, les PR introduisant de nouvelles peer dependencies nécessitent l'approbation d'un mainteneur et doivent être limitées à des circonstances spécifiques.
En général, les packages de types ne devraient avoir une peer dependency que si le package en amont a une peer dependency sur le même package (ou ses types).
Par exemple, un package DT pour un composant React peut spécifier une peer dependency sur @types/react@*
, car le consommateur aura besoin d'installer @types/react
pour utiliser JSX en premier lieu.
Si le consommateur installe @types/react@16
dans son projet, mais qu'une version plus récente de @types/react
est disponible sur npm, la peer dependency peut aider le gestionnaire de packages à choisir @types/react@16
au lieu de cette version plus récente.
De même, chai-as-promised
a une peer dependency sur chai
, donc @types/chai-as-promised
devrait avoir une peer dependency sur @types/chai
.
Il existe certains cas où le package en amont n'a pas de peer dependency sur le package de types, mais une peer dependency est toujours appropriée.
Ce sont généralement des cas où le package en amont étend un autre package et suppose qu'il existe, donc devrait avoir déclaré une peer dependency car il étend un autre package, mais ne l'a pas fait.
Par exemple, chai-match-pattern
étend chai
, mais ne déclare pas de peer dependency sur chai
, mais en a besoin pour fonctionner. @types/chai-match-pattern
devrait avoir une peer dependency sur @types/chai
.
Si un package expose simplement des types d'un autre package dans le cadre de son API en raison d'une dépendance régulière dans le package en amont, il ne devrait pas utiliser une peer dependency.
Par exemple, express
a qs
dans ses "dependencies"
. Lorsque les utilisateurs installent express
, ils n'ont pas besoin d'installer manuellement qs
. De même, @types/express
a @types/qs
dans ses "dependencies"
.
Il serait incorrect de déclarer @types/qs
comme une peer dependency de @types/express
, car cela obligerait certains consommateurs en aval à installer manuellement @types/qs
.
Ce fichier définit quels fichiers doivent être inclus dans chaque package @types
. Il doit prendre une forme spécifique. Pour les packages avec une seule version dans le dépôt :
*
!**/*.d.ts
!**/*.d.cts
!**/*.d.mts
!**/*.d.*.ts
Ce qui signifie "ignorer tous les fichiers, mais ne pas ignorer les fichiers de déclaration". Pour les packages qui ont plus d'une version dans le dépôt, la version "la plus récente" (au niveau supérieur) devrait contenir quelque chose comme :
*
!**/*.d.ts
!**/*.d.cts
!**/*.d.mts
!**/*.d.*.ts
/v15/
/v16/
/v17/
Ce qui est identique au précédent .npmignore
mais en ignorant chaque répertoire enfant versionné.
La CI échouera si ce fichier contient des contenus incorrects et fournira la valeur attendue. Peu importe ce que contient ce fichier, le publisher ne publiera que les fichiers de déclaration.
- Tout d'abord, suivez les conseils du manuel.
- Formatage : dprint est configuré sur ce dépôt, vous pouvez donc lancer
pnpm dprint fmt -- 'path/to/package/**/*.ts'
.- Envisagez d'utiliser le fichier
.vscode/settings.template.json
de VS Code (ou l'équivalent pour d'autres éditeurs) pour formater à la sauvegarde avec l'extension dprint pour VS Code.
- Envisagez d'utiliser le fichier
function sum(nums: number[]): number
: UtilisezReadonlyArray
si une fonction n'écrit pas dans ses paramètres.interface Foo { new(): Foo; }
: Cela définit un type d'objets qui peuvent être modifiés. Vous voudrez probablementdeclare class Foo { constructor(); }
.const Class: { new(): IClass; }
: Il est préférable d'utiliser une déclaration de classeclass Class { constructor(); }
plutôt qu'une constante modifiable.getMeAT<T>(): T
: Si un paramètre de type n'apparaît dans les types d'aucun paramètre, il ne s'agit pas vraiment d'une fonction générique, mais simplement d'une assertion de type déguisée. Il est préférable d'utiliser une assertion de type réelle, par exemplegetMeAT() as number
. Exemple où un paramètre de type est acceptable :function id<T>(value: T): T;
. Exemple où il n'est pas acceptable :function parseJson<T>(json: string): T;
. Exception :new Map<string, number>()
est OK.- L'utilisation des types
Function
etObject
n'est presque jamais une bonne idée. Dans 99% des cas, il est possible de spécifier un type plus spécifique. Les exemples sont(x: number) => number
pour les fonctions et{ x: number, y: number }
pour les objets. S'il n'y a aucune certitude sur le type,any
est le bon choix, pasObject
. Si la seule chose connue à propos du type est qu'il s'agit d'un objet, utilisez le typeobject
, pasObject
ou{ [key: string]: any }
. var foo: string | any
: Lorsqueany
est utilisé dans un type union, le type résultant est toujoursany
. Ainsi, bien que la partiestring
de cette annotation de type puisse look utile, elle n'offre en fait aucune vérification de type supplémentaire par rapport à l'utilisation simple deany
. Selon l'intention, les alternatives acceptables pourraient êtreany
,string
, oustring | object
.
TL;DR : ne pas modifier
.github/CODEOWNERS
, toujours modifier la liste des propriétaires danspackage.json
.
DT a le concept de "propriétaires de définition" qui sont des personnes qui veulent maintenir la qualité des types d'un module particulier.
- En vous ajoutant à la liste, vous serez notifié (via votre nom d'utilisateur GitHub) chaque fois que quelqu'un fera une pull request ou une issue concernant le package.
- Vos reviews de PR auront une plus grande importance pour le bot qui maintient ce repo.
- Les mainteneurs de DT font confiance aux propriétaires des définitions pour assurer un écosystème stable, ne vous ajoutez pas à la légère.
Pour vous ajouter en tant que propriétaire d'une définition, modifiez le tableau owners
dans package.json
:
"owners": [
{
"name": "Some Person",
"githubUsername": "somebody"
},
{
"name": "Some Corp",
"url": "https://example.org"
}
]
Notez que cette liste n'est pas utilisée pour créditer les contributions; il n'est utilisé que pour gérer les reviews des PR.
Une fois par semaine, les propriétaires de définitions sont synchronisés avec le fichier .github/CODEOWNERS qui est notre source de vérité.
Definitely Typed est l'un des dépôts les plus actifs sur GitHub. Vous vous êtes peut-être demandé comment le projet a vu le jour. Un historique de Definitely Typed existe, il a été réalisé par @johnnyreilly. Il raconte les premiers jours de Definitely Typed, depuis un dépôt créé par @borisyankov, jusqu'au moment où il est devenu un élément central de l'écosystème TypeScript. Vous pouvez lire l'histoire de Definitely Typed ici.
La branche master
est automatiquement publiée dans le scope @types
sur npm grâce à DefinitelyTyped-tools.
Cela dépend, mais la plupart des pull requests seront fusionnées en une semaine. Certains PR peuvent être fusionnés par les propriétaires d'un module, et ils peuvent être fusionnés beaucoup plus rapidement. En gros :
Les PRs qui ne modifient que les types d'un module, et qui ont des changements de tests correspondants seront fusionnés beaucoup plus rapidement.
Les PRs qui ont été approuvés par un auteur listé dans l'en-tête de la définition sont généralement fusionnés plus rapidement ; les PRs pour de nouvelles définitions prendront plus de temps car ils nécessitent plus de révision de la part des mainteneurs. Chaque PR est révisé par un membre de l'équipe TypeScript ou Definitely Typed avant d'être fusionné, donc soyez patient car des facteurs humains peuvent causer des retards. Consultez le Pull Request Status Board pour voir les progrès réalisés par les mainteneurs sur les PRs ouverts.
J'aimerais apporter une modification à un projet très populaire, pourquoi sont-ils traités différemment ?
Pour les modifications apportées à des modules très populaires, par exemple Node/Express/Jest, qui sont téléchargés plusieurs millions de fois par semaine sur npm, les exigences en matière de contributions sont un peu plus élevées. Les modifications apportées à ces projets peuvent avoir des effets considérables sur l'écosystème, et nous les traitons donc avec beaucoup d'attention. Ces modules requièrent à la fois l'approbation d'un mainteneur de DT et le soutien enthousiaste des propriétaires du module. La barre pour réussir cela peut être assez haute, et souvent les PRs peuvent s'essouffler parce qu'il n'y a pas de champion. Si vous constatez que personne ne s'engage, essayez de réduire la portée de votre PR.
Les packages npm devraient être mis à jour dans les minutes qui suivent. Si cela fait plus d'une heure, mentionnez le numéro de PR sur le canal Definitely Typed sur le serveur Discord de la communauté TypeScript et le mainteneur actuel demandera au bon membre de l'équipe d'enquêter.
J'écris une définition qui dépend d'une autre définition. Dois-je utiliser <reference types="" />
ou un import ?
Si le module auquel vous faites référence est un module externe (qui utilise export
), utilisez un import.
Si le module auquel vous faites référence est un module ambiant (qui utilise declare module
, ou qui déclare simplement des globaux), utilisez <reference types="" />
.
Certains packages n'ont pas de tslint.json
, et certains tsconfig.json
n'ont pas "noImplicitAny" : true
, "noImplicitThis" : true
, ou "strictNullChecks" : true
.
Alors ils sont faux, et nous ne l'avons pas encore remarqué. Vous pouvez nous aider en soumettant une demande d'extraction pour les corriger.
Oui, en utilisant dprint. Nous recommandons d'utiliser une extension dprint pour votre éditeur.
Alternativement, vous pouvez activer un hook git qui formatera automatiquement votre code. Exécutez pnpm run setup-hooks
. Ensuite, lorsque vous committez, la commande dprint fmt
sera exécutée sur les fichiers modifiés. Si vous utilisez le clone partiel, assurez-vous d'appeler git sparse-checkout add .husky
pour vérifier les hooks git avant d'exécuter le script setup-hooks
.
Les pull requests n'ont pas besoin d'un formatage correct pour être fusionnées. Tout code non formaté sera automatiquement reformaté après avoir été fusionné.
💡 Si vous utilisez VS Code, nous vous suggérons de copier le fichier
.vscode/settings.template.json
vers.vscode/settings.json
. Ce modèle définit l'extension dprint pour VS Code comme le formateur par défaut dans le dépôt.
Voici les définitions actuellement demandées.
Si les types font partie d'un standard web, ils doivent être ajoutés à TypeScript-DOM-lib-generator afin qu'ils puissent faire partie de la lib.dom.d.ts
par défaut.
S'il n'y a pas de code Javascript source du tout, par exemple si vous écrivez des types d'aide ou des types pour une spécification, vous devriez publier les types vous-même, pas sur Definitely Typed.
Parce qu'ils sont destinés à fournir des types pour du code Javascript existant, les packages @types
ne sont pas destinés à être importés directement.
En d'autres termes, vous ne devriez pas créer un package Definitely Typed destiné à être utilisé comme import type { ... } from "@types/foo"
.
Vous ne devez pas non plus vous attendre à écrire import type { ... } from "foo"
quand il n'y a pas de foo
installé.
C'est différent de fournir des types pour une bibliothèque Javascript uniquement pour le navigateur ou des types pour un environnement entier comme node, bun, et al.
Là, les types sont résolus soit implicitement, soit en utilisant /// <references types="foo" />
.
Dois-je ajouter un espace de noms vide à un package qui n'exporte pas de module pour utiliser les importations de style ES6 ??
Certains packages, comme chai-http, exportent une fonction.
Importer ce module avec un import de style ES6 de la forme import * as foo from "foo";
conduit à l'erreur :
erreur TS2497 : Le module 'foo' se résout en une entité non-module et ne peut pas être importé en utilisant cette construction.
Cette erreur peut être supprimée en fusionnant la déclaration de la fonction avec un espace de noms vide du même nom, mais cette pratique est déconseillée. Il s'agit d'une réponse Stack Overflow couramment citée à ce sujet.
Il est plus approprié d'importer le module en utilisant la syntaxe import foo = require("foo");
.
Néanmoins, si vous voulez utiliser un import par défaut comme import foo from "foo";
vous avez deux options :
- vous pouvez utiliser l'option de compilation
--allowSyntheticDefaultImports
si votre module d'exécution supporte un schéma d'interopérabilité pour les modules non-ECMAScript, c'est-à-dire si les importations par défaut fonctionnent dans votre environnement (par exemple Webpack, SystemJS, esm). - vous pouvez utiliser l'option de compilation
--esModuleInterop
si vous voulez que TypeScript prenne en charge l'interopérabilité non-ECMAScript (depuis TypeScript 2.7).
Un package utilise export =
, mais je préfère utiliser les importations par défaut. Puis-je remplacer export =
par export default
?
Comme dans la question précédente, il faut utiliser les options --allowSyntheticDefaultImports
ou --esModuleInterop
du compilateur.
Ne changez pas la définition du type si elle est correcte.
Pour un package npm, export =
est correct si node -p 'require("foo")'
fonctionne pour importer un module, et export default
est correct si node -p 'require("foo").default'
fonctionne pour importer un module.
Vous devrez alors ajouter un commentaire à la dernière ligne de votre en-tête de définition (après // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
): // Minimum TypeScript Version: X.Y
. Ceci définira la version minimale la plus basse supportée.
Cependant, si votre projet a besoin de maintenir des types compatibles avec, disons, 3.7 et plus en même temps que des types compatibles avec 3.6 ou moins, vous devrez utiliser la fonctionnalité typesVersions
.
Vous trouverez une explication détaillée de cette fonctionnalité dans la documentation officielle de TypeScript.
Voici un petit exemple pour commencer :
-
Vous devrez ajouter
typesVersions
aupackage.json
:{ "private": true, "types": "index", "typesVersions": { "<=3.6": { "*": ["ts3.6/*"] } } }
-
Créez le sous-répertoire mentionné dans le champ
typesVersions
à l'intérieur de votre répertoire de types (ts3.6/
dans cet exemple).ts3.6/
supportera les versions de TypeScript 3.6 et inférieures, alors copiez-y les types et tests existants. -
De retour à la racine du package, ajoutez les fonctionnalités de TypeScript 3.7 que vous souhaitez utiliser. Lorsque les gens installeront le package, TypeScript 3.6 et inférieures commenceront à partir de
ts3.6/index.d.ts
, tandis que TypeScript 3.7 et supérieures commenceront à partir deindex.d.ts
.Vous pouvez consulter bluebird pour un exemple.
Cela pourrait être dans TypeScript-DOM-lib-generator. Voir les lignes directrices à cet endroit.
Si le standard est encore à l'état de projet, il a sa place ici.
Utilisez un nom commençant par dom-
et incluez un lien vers le standard comme lien "Project" dans l'en-tête.
Lorsqu'il sort du mode brouillon, nous pouvons le retirer de Definitely Typed et déprécier le packageage @types
associé.
Comment les versions des packages Definitely Typed sont-elles liées aux versions de la bibliothèque correspondante ?
REMARQUE : la discussion dans cette section suppose une certaine familiarité avec le Semantic versioning.
Chaque package de Definitely Typed est versionné lorsqu'il est publié sur npm.
L'outil DefinitelyTyped-tools (l'outil qui publie les packages @types
sur npm) définira la version du package de déclaration en utilisant le numéro de version major.minor.9999
indiqué dans package.json
.
Par exemple, voici les premières lignes des déclarations de type de Node pour la version 20.8.x
au moment de la rédaction :
{
"private": true,
"name": "@types/node",
"version": "20.8.9999"
}
Comme la version est indiquée comme 20.8.9999
, la version npm du package @types/node
sera également 20.8.x
.
Notez que la version dans package.json
ne doit contenir que la version major.minor
(par exemple 10.12
) suivie de .9999
.
Cela est dû au fait que seuls les numéros de version majeure et mineure sont alignés entre les packages de bibliothèque et les packages de déclaration de type. (Le .9999
est utilisé pour s'assurer que les packages locaux @types
sont toujours les plus récents pendant le développement local.)
Le numéro de version patch du package de déclaration de type (par exemple .0
dans 20.8.0
) est initialisé à zéro par Definitely Typed et est incrémenté chaque fois qu'un nouveau package @types/node
est publié sur npm pour la même version majeure/mineure de la bibliothèque correspondante.
Parfois, les versions des packages de déclaration de type et des packages de bibliothèque peuvent être désynchronisées. Voici quelques raisons courantes pour lesquelles cela peut se produire, classées par ordre de gêne pour les utilisateurs d'une bibliothèque. Seul le dernier cas est généralement problématique.
- Comme indiqué ci-dessus, la version patch du package de déclaration de type est indépendante de la version patch de la bibliothèque. Cela permet à Definitely Typed de mettre à jour en toute sécurité les déclarations de type pour la même version majeure/mineure d'une bibliothèque.
- Si vous mettez à jour un package pour de nouvelles fonctionnalités, n'oubliez pas de mettre à jour le numéro de version pour qu'il corresponde à cette version de la bibliothèque.
Si les utilisateurs s'assurent que les versions correspondent entre les packages JavaScript et leurs packages
@types
respectifs, alorsnpm update
devrait généralement fonctionner correctement. - Il est courant que les mises à jour des packages de déclaration de type soient en retard par rapport aux mises à jour des bibliothèques, car ce sont souvent les utilisateurs des bibliothèques, et non les mainteneurs, qui mettent à jour Definitely Typed lorsque de nouvelles fonctionnalités de bibliothèque sont publiées. Il peut donc y avoir un décalage de quelques jours, semaines ou même mois avant qu'un membre de la communauté n'envoie une PR pour mettre à jour le package de déclaration de type pour une nouvelle version de la bibliothèque. Si cela vous impacte, vous pouvez être le changement que vous voulez voir dans le monde et être ce membre de la communauté utile !
❗ Si vous mettez à jour les déclarations de type pour une bibliothèque, définissez toujours la version major.minor
dans package.json
pour qu'elle corresponde à la version de la bibliothèque que vous documentez ! ❗
Si une bibliothèque est mise à jour vers une nouvelle version majeure comportant des changements importants, comment dois-je mettre à jour son package de déclarations de types ?
La gestion sémantique des versions exige que les versions avec des changements majeurs doivent incrémenter le numéro de version majeure.
Par exemple, une bibliothèque qui supprime une fonction exportée publiquement après sa version 3.5.8
doit passer à la version 4.0.0
lors de sa prochaine publication.
De plus, lorsque la version 4.0.0
de la bibliothèque est publiée, le package de déclarations de type Definitely Typed doit également être mis à jour à 4.0.0
, y compris tous les changements majeurs de l'API de la bibliothèque.
De nombreuses bibliothèques ont une grande base d'utilisateurs (y compris les mainteneurs d'autres packages utilisant cette bibliothèque comme dépendance) qui ne passeront pas immédiatement à une nouvelle version avec des changements majeurs, car il peut s'écouler des mois avant qu'un mainteneur ait le temps de réécrire le code pour s'adapter à la nouvelle version. En attendant, les utilisateurs des anciennes versions de la bibliothèque peuvent toujours vouloir mettre à jour les déclarations de type pour les versions plus anciennes.
Si vous avez l'intention de continuer à mettre à jour les déclarations de type de l'ancienne version d'une bibliothèque, vous pouvez créer un nouveau sous-dossier (par exemple /v2/
) nommé d'après la version actuelle (bientôt "ancienne") et y copier les fichiers existants de la version actuelle.
Lors de la création d'un nouveau dossier de version, assurez-vous que le champ version de package.json
a été mis à jour ; pnpm
résoudra automatiquement ce package versionné chaque fois que nécessaire. Si d'autres packages dans le dépôt doivent dépendre de cette nouvelle version, assurez-vous que leurs package.json
soient également mis à jour.
Par exemple, si nous créons types/history/v2
, son package.json
ressemblerait à ceci :
{
"private": true,
"name": "@types/history",
"version": "2.4.9999"
}
Un autre package peut sélectionner cette version en spécifiant :
{
"private": true,
"name": "@types/browser-sync",
"version": "2.26.9999",
"dependencies": {
"@types/history": "^2"
}
}
De plus, /// <reference types=".." />
ne fonctionnera pas avec le mappage de chemin, donc les dépendances doivent utiliser import
.
Comment fonctionnent les changements de type majeurs si les packages de déclaration de type suivent de près la version du package de la bibliothèque ?
Les packages @types
typent toujours les packages de la même version, donc @types/foo@5.4.x
sont pour foo@5.4.x
.
En conséquence, tous les changements, qu'ils soient majeurs ou non, sont publiés en tant que révisions de correctifs, sauf s'ils sont accompagnés d'une augmentation majeure/mineure pour changer la version du package ciblé (coïncidence ou non).
En ce qui concerne les changements majeurs, les mainteneurs de DT prennent en compte la popularité du package, les avantages du changement proposé, l'effort nécessaire pour que les utilisateurs corrigent leur code, et si le changement pourrait raisonnablement être retardé jusqu'à ce qu'il puisse être synchronisé avec une augmentation majeure de la bibliothèque en amont.
Comment puis-je écrire des définitions pour des packages qui peuvent être utilisés globalement et en tant que module ?
Le manuel TypeScript contient d'excellentes informations générales sur l'écriture de définitions, ainsi que cet exemple de fichier de définition qui montre comment créer une définition en utilisant la syntaxe de module de style ES6, tout en spécifiant également les objets mis à la disposition de la portée globale. Cette technique est démontrée en pratique dans la définition de big.js
, qui est une bibliothèque qui peut être chargée globalement via une balise script sur une page web, ou importée via require ou des importations de style ES6.
Pour tester comment votre définition peut être utilisée à la fois lorsqu'elle est référencée globalement ou en tant que module importé, créez un dossier test
, et placez-y deux fichiers de test. Nommez l'un VotreNomBibliothèque-global.test.ts
et l'autre VotreNomBibliothèque-module.test.ts
. Le fichier de test global doit exercer la définition de la manière dont elle serait utilisée dans un script chargé sur une page web où la bibliothèque est disponible sur la portée globale - dans ce scénario, vous ne devez pas spécifier d'instruction d'importation. Le fichier de test module doit exercer la définition selon la façon dont elle serait utilisée lorsqu'elle est importée (y compris la ou les déclarations import
). Si vous spécifiez une propriété files
dans votre fichier tsconfig.json
, assurez-vous d'inclure les deux fichiers de test. Un exemple pratique de ceci est aussi disponible sur la définition de big.js
.
Il suffit de tester uniquement les éléments accessibles globalement dans le fichier de test global et d'exercer pleinement la définition dans le fichier de test du module, ou vice versa.
Les types pour un package avec un scope @foo/bar
doivent être placés dans types/foo__bar
. Notez le double underscore.
Ce projet est placé sous la licence MIT.
Les droits d'auteur sur les fichiers de définition appartiennent à chaque contributeur mentionné au début de chaque fichier de définition.