El repositorio de definiciones de tipos TypeScript de alta calidad .
¡También puedes leer este README en español, 한국어, Русский, 简体中文, Português, Italiano, 日本語 y Français!
Enlace al manual de administración
Definitivamente Typed ha cambiado recientemente a un monorepo pnpm
adecuado; es posible que desee volver a leer este documento para conocer los cambios en el diseño de los paquetes en este repositorio.
Como mínimo, es posible que desees git clean -fdx
el repositorio (o node ./scripts/clean-node-modules.js
en Windows) para limpiar node_modules
y ejecutar pnpm install --filter .
para instalar la raíz del espacio de trabajo. Consulte otras secciones para obtener más información sobre pnpm install
.
Esta sección realiza un seguimiento del estado del repositorio y del proceso de publicación. Puede resultar útil para los contribuyentes que experimenten algún problema con sus relaciones públicas y paquetes.
Si algo aquí parece incorrecto o cualquiera de los anteriores falla, háganoslo saber en el canal Definitely Typed en el servidor TypeScript Community Discord.
Consulte el manual de TypeScript.
Este es el método preferido. Por ejemplo:
npm install --save-dev @types/node
Para instalar tipificaciones para un módulo con alcance, elimine @
y agregue un guión bajo doble después del alcance. Por ejemplo, para instalar mecanografía para @babel/preset-env
:
npm install --save-dev @types/babel__preset-env
Luego, el compilador debería incluir automáticamente los tipos. Es posible que deba agregar una referencia types
si no está utilizando módulos:
/// <reference types="node" />
Ver más en el manual.
Para un paquete npm "foo", la escritura será en "@types/foo".
Si su paquete tiene tipos especificados usando la clave types
o typings
en su package.json
, el registro npm mostrará que el paquete tiene enlaces disponibles de esta manera:
Puedes clonar todo el repositorio como de costumbre, pero es grande e incluye un directorio enorme de paquetes de tipos. La clonación llevará algún tiempo y puede resultar innecesariamente difícil de manejar.
Para obtener un clon más manejable que incluya solo los paquetes de tipo relevantes para usted, puede usar las funciones sparse-checkout
y --filter
de git. Esto reducirá el tiempo de clonación y mejorará el rendimiento de git.
️ Esto requiere una versión mínima de git 2.27.0, que probablemente sea más nueva que la predeterminada en la mayoría de las máquinas. Hay procedimientos más complicados disponibles en versiones anteriores, pero no se tratan en esta guía.
git clone --sparse --filter=blob:none <forkedUrl>
--sparse
inicializa el archivo de pago disperso para que el directorio de trabajo comience solo con los archivos en la raíz del repositorio.--filter=blob:none
incluirá todo el historial de confirmaciones, pero excluirá los archivos y los recuperará solo cuando sea necesario.git sparse-checkout add types/<type> types/<dependency-type> ...
pnpm test <package to test>
. Cuando realiza un PR para editar un paquete existente, dt-bot
debe @mencionar a los propietarios del paquete. Si no es así, puede hacerlo usted mismo en el comentario asociado con el PR.
Si usted es el autor de la biblioteca y su paquete está escrito en TypeScript, agrupe los archivos de declaración generados en su paquete en lugar de publicarlos en Definitely Typed. También puede generar archivos de declaración a partir de archivos JavaScript, utilizando JSDoc para anotaciones de tipo.
Si está agregando tipos para un paquete npm, cree un directorio con el mismo nombre. Si el paquete para el que está agregando tipos no está en npm, asegúrese de que el nombre que elija no entre en conflicto con el nombre de un paquete en npm. (Puede utilizar npm info <my-package>
para comprobar la existencia del paquete <my-package>
).
Su paquete debe tener esta estructura:
Archivo | Objetivo |
---|---|
index.d.ts | Este contiene los tipos del paquete. |
<my-package>-tests.ts | Contiene un código de muestra que prueba los tipos. Este código no se ejecuta, pero está verificado. |
tsconfig.json | Esto le permite ejecutar tsc dentro del paquete. |
.eslintrc.json | (Rara vez) Solo es necesario para deshabilitar las reglas de pelusa escritas para eslint. |
package.json | Contiene metadatos para el paquete, incluido su nombre, versión y dependencias. |
.npmignore | Especifica qué archivos se pretende incluir en el paquete. |
Generelos ejecutando npx dts-gen --dt --name <my-package> --template module
. Vea todas las opciones en dts-gen.
Si tiene archivos .d.ts
además de index.d.ts
, asegúrese de que se haga referencia a ellos en index.d.ts
o en las pruebas.
Los miembros de Definitely Typed monitorean rutinariamente la aparición de nuevos RP, aunque tengan en cuenta que la cantidad de otros RP puede ralentizar las cosas.
Para ver un buen paquete de ejemplo, consulte base64-js.
Cuando un paquete incluye sus propios tipos, los tipos deben eliminarse de Definitely Typed para evitar confusiones.
Puede eliminarlo ejecutando pnpm run not-needed <typingsPackageName> <asOfVersion> [<libraryName>]
.
<typingsPackageName>
: este es el nombre del directorio que se va a eliminar.<asOfVersion>
: se publicará un código auxiliar en @types/<typingsPackageName>
con esta versión. Debe ser superior a cualquier versión publicada actualmente y debe ser una versión de <libraryName>
en npm.<libraryName>
: Nombre del paquete npm que reemplaza los tipos Definitely Typed. Por lo general, esto es idéntico a <typingsPackageName>
, en cuyo caso puede omitirlo. Si un paquete nunca estuvo en Definitely Typed, no es necesario agregarlo a notNeededPackages.json
.
Pruebe sus cambios ejecutando pnpm test <package to test>
donde <package to test>
es el nombre de su paquete. Debe ejecutar esto desde el directorio DefinitelyTyped porque los paquetes.jsons individuales no definen scripts de prueba.
Este script utiliza dtslint para ejecutar el compilador TypeScript en sus archivos dts.
Una vez que tenga todos los cambios listos, use pnpm run test-all
para ver cómo sus cambios afectan a otros módulos.
attw
) comprobaciones dtslint incluye comprobaciones de configuración de formato de módulo y package.json
de @arethetypeswrong/cli. Las comprobaciones se ejecutan solo si se puede encontrar un paquete de implementación compatible con SemVer major en npm para compararlo con el paquete DefinitelyTyped. (Se omiten los paquetes DefinitelyTyped marcados como nonNpm
en su package.json
).
Actualmente, muchos paquetes no superan las comprobaciones attw
y deben corregirse. Para permitirnos lograr un progreso incremental, las comprobaciones fallidas attw
no fallan en la ejecución dtslint
cuando el paquete aparece en failingPackages
en attw.json
, pero aún así se informarán en la salida de pnpm test my-package
. Si repara el paquete, elimínelo de failingPackages
para que las comprobaciones attw
puedan comenzar a fallar en las ejecuciones dtslint
.
Todos los problemas informados por attw
tienen documentación vinculada en el resultado. Algunas reglas generales para ayudar a evitar problemas:
El package.json
en el paquete DefinitelyTyped debe tener campos type
y exports
coincidentes si el paquete de implementación los usa en su package.json
. Por ejemplo, si un package.json
de implementación.json tiene el siguiente aspecto:
{
"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 "
}
}
}
entonces el package.json
DefinitelyTyped.json debería verse así:
{
"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"
}
}
}
Observe que cada subruta exports
se refleja y que cada archivo JavaScript tiene un archivo de declaración correspondiente con una extensión de archivo coincidente: un archivo .d.ts
escribe un archivo .js
, no un archivo .mjs
o .cjs
.
Cuando el paquete de implementación usa module.exports = ...
, el paquete DefinitelyTyped debe usar export =
, no export default
. (Alternativamente, si module.exports
es solo un objeto de propiedades con nombre, el paquete DefinitelyTyped puede usar una serie de exportaciones con nombre). El obstáculo más común para corregir este problema es la confusión sobre cómo exportar tipos además de la exportación principal. Por ejemplo, supongamos que estos tipos utilizan incorrectamente export default
:
export interface Options {
// ...
}
export default function doSomething ( options : Options ) : void ;
Cambiar el export default
a una export =
crea un error:
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.
Para solucionar este problema, mueva los tipos dentro de un espacio de nombres con el mismo nombre que la función:
declare namespace doSomething {
export interface Options {
// ...
}
}
declare function doSomething ( options : doSomething . Options ) : void ;
export = doSomething ;
Si necesita ayuda para solucionar un problema, pregunte en el canal DefinitelyTyped en el servidor de TypeScript Community Discord.
Si está agregando tipos para un paquete npm, cree un directorio con el mismo nombre. Si el paquete para el que está agregando tipos no está en npm, configure "nonNpm": true
en package.json
y asegúrese de que el nombre que elija no entre en conflicto con el nombre de un paquete en npm. (Puede utilizar npm info <my-package>
para comprobar la existencia del paquete <my-package>
).
En raras ocasiones, nonNpm
puede configurarse en "conflict"
, lo que indica que hay un paquete en npm con el mismo nombre, pero los tipos entran en conflicto intencionalmente con ese paquete. Esto puede ser cierto para paquetes que definen un entorno como @types/node
o para paquetes ficticios como aws-lambda
. Evite utilizar "conflict"
siempre que sea posible.
<my-package>-tests.ts
Debería haber un archivo <my-package>-tests.ts
, que se considera su archivo de prueba, junto con cualquier archivo *.ts
que importe. Si no ve ningún archivo de prueba en la carpeta del módulo, cree un <my-package>-tests.ts
. Estos archivos se utilizan para validar la API exportada desde los archivos *.d.ts
que se envían como @types/<my-package>
. Ellos mismos no realizan envíos.
Los cambios en los archivos *.d.ts
deben incluir un cambio en el archivo *.ts
correspondiente que muestre la API que se utiliza, para que alguien no rompa accidentalmente el código del que usted depende. Por ejemplo, este cambio a una función en un archivo .d.ts
agrega un nuevo parámetro a una función:
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("//", { })
Si se pregunta por dónde empezar con el código de prueba, los ejemplos en el archivo README del paquete original son un excelente lugar para comenzar.
Puede validar sus cambios con npm test <package to test>
desde la raíz de este repositorio, que tiene en cuenta los archivos modificados.
Utilice $ExpectType
para afirmar que una expresión es de un tipo determinado y @ts-expect-error
para afirmar que se trata de un error de compilación. Ejemplos:
// $ExpectType void
f ( 1 ) ;
// @ts-expect-error
f ( "one" ) ;
Para obtener más detalles, consulte el archivo Léame de dtslint.
.eslintrc.json
Si por alguna razón es necesario deshabilitar una regla de pelusa, deshabilítela para una línea específica:
// eslint-disable-next-line no-const-enum
const enum Const {
One ,
}
const enum Enum { // eslint-disable-line no-const-enum
Two ,
}
Aún puede deshabilitar reglas con .eslintrc.json, pero no debería hacerlo en paquetes nuevos. Deshabilitar las reglas para todo el paquete hace que sea más difícil de revisar.
tsconfig.json
tsconfig.json
debe tener noImplicitAny
, noImplicitThis
, strictNullChecks
y strictFunctionTypes
establecidos en true
.
Puede editar tsconfig.json
para agregar nuevos archivos de prueba, agregar "target": "es6"
(necesario para funciones asíncronas), agregarlo a "lib"
o agregar la opción del compilador "jsx"
.
esModuleInterop
/ allowSyntheticDefaultImports
TL;DR: esModuleInterop
y allowSyntheticDefaultImports
no están permitidos en su tsconfig.json
.
Estas opciones permiten escribir una importación predeterminada para una exportación CJS, modelando la interoperabilidad integrada entre los módulos CJS y ES en Node y en algunos paquetes 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" ;Dado que la validez en tiempo de compilación de la importación en
index.d.ts
depende de configuraciones de compilación específicas, que los usuarios de sus tipos no heredan, usar este patrón en DefinitelyTyped obligaría a los usuarios a cambiar sus propias configuraciones de compilación, que podrían ser incorrectas. para su tiempo de ejecución. En su lugar, debe escribir una importación CJS para una exportación CJS para garantizar una compatibilidad generalizada e independiente de la configuración:// index.d.ts // CJS import, modeling `const Component = require("./component")` in JS import Component = require ( "./component" ) ;
package.json
Este archivo es obligatorio y debe seguir esta plantilla:
{
"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
especifica todas las dependencias, incluidos otros paquetes @types
.
Debe agregar dependencias que no sean @types
a la lista de dependencias externas permitidas. Pikaday es un buen ejemplo. Estas adiciones son aprobadas por un mantenedor, lo que nos da la oportunidad de asegurarnos de que los paquetes @types
no dependan de paquetes maliciosos.
Si el paquete de implementación usa ESM y especifica "type": "module"
, entonces debes modificar package.json para que coincida:
{
"type" : " module "
}
Esto también se aplica si el paquete de implementación tiene exports
en su paquete.json.
Definitivamente Typed permite peerDependencies
en package.json
. Las dependencias entre pares pueden ayudar a evitar situaciones en las que un administrador de paquetes instala inesperadamente versiones demasiado nuevas o más de una versión del mismo paquete. Sin embargo, las dependencias entre pares tienen desventajas; Los administradores de paquetes difieren en su manejo de las dependencias entre pares (por ejemplo, yarn
no las instala automáticamente, npm
requiere --legacy-peer-deps
para las discrepancias). Como tal, los RP que introducen nuevas dependencias entre pares requieren la aprobación del mantenedor y deben limitarse a circunstancias específicas.
En general, los paquetes de tipos solo deben tener una dependencia de pares si el paquete ascendente tiene una dependencia de pares en el mismo paquete (o sus tipos). Por ejemplo, un paquete DT para un componente React puede especificar una dependencia de pares en @types/react@*
, ya que el consumidor habrá necesitado instalar @types/react
para usar JSX en primer lugar. Si el consumidor instala @types/react@16
en su proyecto, pero hay una versión más nueva de @types/react
disponible en npm, la dependencia entre pares puede ayudar al administrador de paquetes a elegir @types/react@16
en lugar de esa versión más nueva. De manera similar, chai-as-promised
tiene una dependencia de pares en chai
, por lo que @types/chai-as-promised
debería tener una dependencia de pares en @types/chai
.
Hay algunos casos en los que el paquete ascendente no tiene una dependencia de pares en el paquete de tipos, pero una dependencia de pares sigue siendo apropiada. Estos son casos típicos en los que el paquete ascendente extiende otro paquete y asume que existe, por lo que debería haber declarado una dependencia entre pares cuando extiende otro paquete, pero no lo hizo. Por ejemplo, chai-match-pattern
extiende chai
, pero no declara una dependencia de pares en chai
, pero lo necesita para funcionar. @types/chai-match-pattern
debe tener una dependencia de igual en @types/chai
.
Si un paquete simplemente expone tipos de otro paquete como parte de su API debido a una dependencia regular en el paquete ascendente, no debería usar una dependencia entre pares. Por ejemplo, express
tiene qs
en sus "dependencies"
. Cuando los usuarios instalan express
, no necesitan instalar qs
manualmente. Asimismo, @types/express
tiene @types/qs
en sus "dependencies"
. Sería incorrecto declarar @types/qs
como una dependencia de pares de @types/express
, ya que eso requeriría que algunos consumidores posteriores instalen @types/qs
manualmente.
.npmignore
Este archivo define qué archivos se incluirán en cada paquete @types
. Debe adoptar una forma específica. Para paquetes con una sola versión en el repositorio:
*
! ** / * .d.ts
! ** / * .d.cts
! ** / * .d.mts
! ** / * .d. * .ts
Es decir, "ignorar todos los archivos, pero no ignorar ningún archivo de declaración". Para paquetes que tienen más de una versión en el repositorio, la versión "más reciente" (en el nivel superior) debe contener algo como:
*
! ** / * .d.ts
! ** / * .d.cts
! ** / * .d.mts
! ** / * .d. * .ts
/ v15 /
/ v16 /
/ v17 /
Que es lo mismo que el .npmignore
anterior pero ignorando cada uno de los directorios secundarios versionados.
CI fallará si este archivo contiene contenidos incorrectos y proporciona el valor deseado. No importa lo que contenga este archivo, el editor solo publicará archivos de declaración.
pnpm dprint fmt -- 'path/to/package/**/*.ts'
..vscode/settings.template.json
(o equivalente para otros editores) para formatear al guardar con la extensión dprint de VS Codefunction sum(nums: number[]): number
: use ReadonlyArray
si una función no escribe en sus parámetros.interface Foo { new(): Foo; }
: Esto define un tipo de objetos que son nuevos. Probablemente quieras declare class Foo { constructor(); }
.const Class: { new(): IClass; }
: Prefiere utilizar una declaración de clase class Class { constructor(); }
en lugar de una constante nueva.getMeAT<T>(): T
: Si un parámetro de tipo no aparece en los tipos de ningún parámetro, en realidad no tiene una función genérica, solo tiene una aserción de tipo disfrazada. Prefiere utilizar una afirmación de tipo real, por ejemplo, getMeAT() as number
. Ejemplo donde un parámetro de tipo es aceptable: function id<T>(value: T): T;
. Ejemplo donde no es aceptable: function parseJson<T>(json: string): T;
. Excepción: new Map<string, number>()
está bien.Function
y Object
casi nunca es una buena idea. En el 99% de los casos es posible especificar un tipo más específico. Algunos ejemplos son (x: number) => number
para funciones y { x: number, y: number }
para objetos. Si no hay ninguna certeza sobre el tipo, any
es la opción correcta, no Object
. Si el único hecho conocido sobre el tipo es que es algún objeto, use el tipo object
, no Object
o { [key: string]: any }
.var foo: string | any
: cuando se utiliza any
en un tipo de unión, el tipo resultante sigue siendo any
. Entonces, si bien la parte string
de esta anotación de tipo puede parecer útil, de hecho no ofrece verificación de tipos adicional a la del simple uso any
. Dependiendo de la intención, las alternativas aceptables podrían ser any
string
o string | object
.TL;DR: no modifique
.github/CODEOWNERS
, modifique siempre la lista de propietarios enpackage.json
.
DT tiene el concepto de "Propietarios de definición", que son personas que desean mantener la calidad de los tipos de un módulo en particular.
Para agregarse como propietario de definición, modifique la matriz owners
en package.json
:
"owners" : [
{
"name" : " Some Person " ,
"githubUsername" : " somebody "
},
{
"name" : " Some Corp " ,
"url" : " https://example.org "
}
]
Tenga en cuenta que esta lista no se utiliza para otorgar crédito por contribuciones; solo se utiliza para gestionar revisiones de relaciones públicas.
Una vez a la semana, los propietarios de la definición se sincronizan con el archivo .github/CODEOWNERS, que es nuestra fuente de información.
Definitivamente Typed es uno de los repositorios más activos en GitHub. Quizás te hayas preguntado cómo surgió el proyecto. @johnnyreilly escribió una historia de Definitely Typed. Cuenta la historia de los primeros días de Definitely Typed, desde un repositorio creado por @borisyankov, hasta el punto en que se convirtió en una parte fundamental del ecosistema TypeScript. Puedes leer la historia de Definitely Typed aquí.
@types
en npm? La rama master
se publica automáticamente en el ámbito @types
en npm gracias a DefinitelyTyped-tools.
Depende, pero la mayoría de las solicitudes de extracción se fusionarán en una semana. Los propietarios de un módulo pueden fusionar algunos RP y pueden fusionarlos mucho más rápido. Apenas:
Los RP que solo cambian los tipos de un módulo y tienen cambios de prueba correspondientes se fusionarán mucho más rápido
Los RP que han sido aprobados por un propietario que figura en el package.json
de la definición generalmente se fusionan más rápidamente; Los RP para nuevas definiciones llevarán más tiempo ya que requieren más revisión por parte de los mantenedores. Cada PR es revisado por un miembro del equipo de TypeScript o Definitely Typed antes de fusionarse, así que tenga paciencia ya que los factores humanos pueden causar retrasos. Consulte el tablero de estado de la nueva solicitud de extracción para ver el progreso a medida que los mantenedores trabajan en los RP abiertos.
Para cambios en módulos muy populares, por ejemplo, Node/Express/Jest, que tienen muchos millones de descargas cada uno por semana en npm, los requisitos de contribuciones son un poco más altos. Los cambios en estos proyectos pueden tener efectos masivos en el ecosistema, por lo que los tratamos con mucho cuidado. Estos módulos requieren tanto la aprobación de un mantenedor de DT como el apoyo entusiasta de los propietarios del módulo. El listón para superar esto puede ser bastante alto y, a menudo, los RP pueden quedar obsoletos porque no tienen un campeón. Si descubre que nadie se compromete, intente que sus relaciones públicas tengan un enfoque menor.
@types
npm?Los paquetes npm deberían actualizarse en una hora. Si ha pasado más de una hora, mencione el número de PR en el canal Definitely Typed en el servidor de TypeScript Community Discord y el mantenedor actual buscará al miembro correcto del equipo para investigar.
<reference types="" />
o una importación? Si el módulo al que hace referencia es un módulo (usa export
), use una importación. Si el módulo al que hace referencia es un módulo ambiental (usa declare module
) o simplemente declara globales, use <reference types="" />
.
tsconfig.json
al que le falta "noImplicitAny": true
, "noImplicitThis": true
o "strictNullChecks": true
.Entonces se equivocan y todavía no nos hemos dado cuenta. Puedes ayudar enviando una solicitud de extracción para solucionarlos.
Sí, usando dprint. Recomendamos utilizar una extensión dprint para su editor.
Alternativamente, puede habilitar un gancho git que formateará su código automáticamente. Ejecute pnpm run setup-hooks
. Luego, cuando realice la confirmación, el comando dprint fmt
se ejecutará en los archivos modificados. Si aprovecha la clonación parcial, asegúrese de llamar git sparse-checkout add .husky
para verificar los ganchos de git antes de ejecutar el script setup-hooks
.
Las solicitudes de extracción no requieren un formato correcto para fusionarse. Cualquier código sin formato se reformateará automáticamente después de fusionarse.
Si es usuario de VS Code, le sugerimos copiar el archivo
.vscode/settings.template.json
a.vscode/settings.json
. Esa plantilla establece la extensión dprint VS Code como el formateador predeterminado en el repositorio.
Aquí están las definiciones solicitadas actualmente.
Si los tipos son parte de un estándar web, se deben contribuir a TypeScript-DOM-lib-generator para que puedan convertirse en parte del lib.dom.d.ts
predeterminado.
Si no hay ningún código fuente JavaScript, por ejemplo, si está escribiendo tipos auxiliares o tipos para una especificación, debe publicar los tipos usted mismo, no en Definitely Typed. Debido a que están destinados a proporcionar tipos para el código JavaScript existente, los paquetes @types
no deben importarse directamente. Es decir, no debe crear un paquete Definitely Typed que deba usarse como import type { ... } from "@types/foo"
. Tampoco debe esperar escribir import type { ... } from "foo"
cuando no hay foo
instalado.
Esto es diferente de proporcionar tipos para una biblioteca JavaScript solo del navegador o tipos para un entorno completo como node, bun, et al. Allí, los tipos se resuelven implícitamente o usando /// <references types="foo" />
.
Algunos paquetes, como chai-http, exportan una función.
Importando este módulo con una importación de estilo ES6 en el formulario import * as foo from "foo";
conduce al error:
error TS2497: el módulo 'foo' se resuelve en una entidad que no es un módulo y no se puede importar utilizando esta construcción.
Este error se puede suprimir fusionando la declaración de función con un espacio de nombres vacío del mismo nombre, pero se desaconseja esta práctica. Esta es una respuesta de Stack Overflow comúnmente citada con respecto a este asunto.
Es más apropiado importar el módulo usando import foo = require("foo");
sintaxis. Sin embargo, si desea utilizar una importación predeterminada como import foo from "foo";
tienes dos opciones:
--allowSyntheticDefaultImports
si el tiempo de ejecución de su módulo admite un esquema de interoperabilidad para módulos que no son ECMAScript, es decir, si las importaciones predeterminadas funcionan en su entorno (por ejemplo, Webpack, SystemJS, esm).--esModuleInterop
si desea que TypeScript se encargue de la interoperabilidad que no es ECMAScript (desde TypeScript 2.7). export =
, pero prefiero usar importaciones predeterminadas. ¿Puedo cambiar export =
para export default
? Al igual que en la pregunta anterior, consulte el uso de las opciones del compilador --allowSyntheticDefaultImports
o --esModuleInterop
.
No cambie la definición de tipo si es precisa. Para un paquete npm, export =
es preciso si node -p 'require("foo")'
funciona para importar un módulo y export default
es preciso si node -p 'require("foo").default'
funciona para importar un módulo .
Luego habrá configurado la versión mínima admitida especificando "minimumTypeScriptVersion": "XY"
en package.json
.
Sin embargo, si su proyecto necesita mantener tipos que sean compatibles con, digamos, 3.7 y superiores al mismo tiempo que tipos que sean compatibles con 3.6 o inferiores, deberá utilizar la función typesVersions
. Puede encontrar una explicación detallada de esta característica en la documentación oficial de TypeScript.
Aquí hay un breve ejemplo para comenzar:
Tendrás que agregar typesVersions
a package.json
:
{
"private" : true ,
"types" : " index " ,
"typesVersions" : {
"<=3.6" : { "*" : [ " ts3.6/* " ] }
}
}
Cree el subdirectorio mencionado en el campo typesVersions
dentro de su directorio de tipos ( ts3.6/
en este ejemplo). ts3.6/
admitirá las versiones 3.6 y posteriores de TypeScript, así que copie los tipos y pruebas existentes allí.
De vuelta en la raíz del paquete, agregue las funciones de TypeScript 3.7 que desea utilizar. Cuando las personas instalen el paquete, TypeScript 3.6 y versiones anteriores comenzarán desde ts3.6/index.d.ts
, mientras que TypeScript 3.7 y versiones posteriores comenzarán desde index.d.ts
.
Puedes mirar a bluebird como ejemplo.
Esto puede pertenecer a TypeScript-DOM-lib-generator. Vea las pautas allí. Si la norma es todavía un borrador, pertenece aquí. Utilice un nombre que comience con dom-
e incluya un enlace al estándar como enlace "Proyecto" en package.json
. Cuando salga del modo borrador, podemos eliminarlo de Definitely Typed y desaprobar el paquete @types
asociado.
NOTA: La discusión en esta sección asume familiaridad con el control de versiones semántico.
Cada paquete Definitely Typed tiene una versión cuando se publica en npm. DefinitelyTyped-tools (la herramienta que publica paquetes @types
en npm) establecerá la versión del paquete de declaración utilizando el número de versión major.minor.9999
que figura en package.json
. Por ejemplo, aquí están las primeras líneas de las declaraciones de tipo de Node para la versión 20.8.x
al momento de escribir este artículo:
{
"private" : true ,
"name" : " @types/node " ,
"version" : " 20.8.9999 "
}
Debido a que la versión aparece como 20.8.9999
, la versión npm del paquete @types/node
también será 20.8.x
Tenga en cuenta que la versión en package.json
solo debe contener la versión major.minor
(por ejemplo, 10.12
) seguida de .9999
. Esto se debe a que sólo los números de versión mayor y menor están alineados entre los paquetes de biblioteca y los paquetes de declaración de tipos. (El .9999
es para garantizar que los paquetes @types
locales sean siempre los más nuevos durante el desarrollo local). El número de versión del parche del paquete de declaración de tipo (por ejemplo .0
en 20.8.0
) se inicializa a cero mediante Definitely Typed y se incrementa cada vez. Se publica un nuevo paquete @types/node
en npm para la misma versión principal/menor de la biblioteca correspondiente.
A veces, las versiones del paquete de declaración de tipos y las versiones del paquete de biblioteca pueden no estar sincronizadas. A continuación se presentan algunas razones comunes, en orden de cuán inconvenientes son para los usuarios de una biblioteca. Sólo el último caso suele ser problemático.
@types
, entonces npm update
normalmente debería funcionar. ❗ Si está actualizando declaraciones de tipo para una biblioteca, configure siempre la versión major.minor
en package.json
para que coincida con la versión de la biblioteca que está documentando. ❗
El control de versiones semántico requiere que las versiones con cambios importantes incrementen el número de versión principal. Por ejemplo, una biblioteca que elimina una función exportada públicamente después de su versión 3.5.8
debe aumentar su versión a 4.0.0
en su próxima versión. Además, cuando salga la versión 4.0.0
de la biblioteca, su paquete de declaración de tipo Definitely Typed también debería actualizarse a 4.0.0
, incluidos los cambios importantes en la API de la biblioteca.
Muchas bibliotecas tienen una gran base instalada de desarrolladores (incluidos los mantenedores de otros paquetes que usan esa biblioteca como dependencia) que no migrarán de inmediato a una nueva versión que tenga cambios importantes, porque pueden pasar meses hasta que un mantenedor tenga tiempo de reescribir. Código para adaptarse a la nueva versión. Mientras tanto, es posible que los usuarios de versiones antiguas de la biblioteca aún deseen actualizar las declaraciones de tipos para versiones anteriores.
Si tiene la intención de continuar actualizando la versión anterior de las declaraciones de tipo de una biblioteca, puede crear una nueva subcarpeta (por ejemplo /v2/
) con el nombre de la versión actual (que pronto será "antigua") y copiar en ella los archivos existentes de la versión actual. .
Al crear una nueva carpeta de versión, asegúrese de que el campo de versión de package.json
se haya actualizado; pnpm
se resolverá automáticamente en este paquete versionado cuando sea necesario. Si otros paquetes en el repositorio necesitan depender de esta nueva versión, asegúrese de que sus package.json
también estén actualizados.
Por ejemplo, si estamos creando types/history/v2
, su package.json
se vería así:
{
"private" : true ,
"name" : " @types/history " ,
"version" : " 2.4.9999 "
}
Otro paquete puede seleccionar esta versión especificando:
{
"private" : true ,
"name" : " @types/browser-sync " ,
"version" : " 2.26.9999 " ,
"dependencies" : {
"@types/history" : " ^2 "
}
}
Además, /// <reference types=".." />
no funcionará con el mapeo de rutas, por lo que las dependencias deben usar import
.
Los paquetes @types
siempre escriben paquetes de la misma versión, por lo que @types/[email protected]
son para [email protected]
. Como consecuencia, todos los cambios, importantes o no, se publican como revisiones de parches, a menos que se combinen con un aumento mayor/menor para cambiar la versión del paquete al que se dirige (casualmente o no).
Cuando se trata de cambios importantes, los mantenedores de DT consideran la popularidad del paquete, las ventajas del cambio importante propuesto, el esfuerzo que será necesario para que los usuarios arreglen su código y si el cambio podría retrasarse razonablemente hasta que pueda sincronizarse. con un importante aumento de la biblioteca ascendente.
El manual de TypeScript contiene excelente información general sobre cómo escribir definiciones y también este archivo de definición de ejemplo que muestra cómo crear una definición utilizando la sintaxis del módulo de estilo ES6, al mismo tiempo que especifica los objetos disponibles para el ámbito global. Esta técnica se demuestra prácticamente en la definición de big.js
, que es una biblioteca que se puede cargar globalmente mediante una etiqueta script en una página web o importar mediante importaciones requeridas o de estilo ES6.
Para probar cómo se puede usar su definición cuando se hace referencia globalmente o como un módulo importado, cree una carpeta test
y coloque dos archivos de prueba allí. Nombra uno YourLibraryName-global.test.ts
y el otro YourLibraryName-module.test.ts
. El archivo de prueba global debe ejercitar la definición de acuerdo con cómo se usaría en un script cargado en una página web donde la biblioteca está disponible en el ámbito global; en este escenario, no debe especificar una declaración de importación. El archivo de prueba del módulo debe ejercitar la definición de acuerdo con cómo se usaría cuando se importe (incluidas las declaraciones import
). Si especifica una propiedad files
en su archivo tsconfig.json
, asegúrese de incluir ambos archivos de prueba. Un ejemplo práctico de esto también está disponible en la definición big.js
Tenga en cuenta que no es necesario ejercer completamente la definición en cada archivo de prueba: es suficiente probar solo los elementos accesibles a nivel mundial en el archivo de prueba global y ejercer completamente la definición en el archivo de prueba del módulo o viceversa.
Los tipos para un paquete de alcance @foo/bar
deben ir en types/foo__bar
. Tenga en cuenta el doble bajo.
Este proyecto está bajo la licencia MIT.
Los derechos de autor en los archivos de definición son respectivos de cada contribuyente que figura al comienzo de cada archivo de definición.