O repositório para definições de tipo TypeScript de alta qualidade .
Você também pode ler este README em Español, 한국어, Русский, 简体中文, Português, Italiano, 日本語 e Français!
Link para o manual do administrador
Definitivamente Typed mudou recentemente para um monorepo pnpm
adequado; você pode querer reler este documento para mudanças no layout dos pacotes neste repositório.
No mínimo, você pode querer git clean -fdx
o repositório (ou node ./scripts/clean-node-modules.js
no Windows) para limpar node_modules
e executar pnpm install --filter .
para instalar a raiz do espaço de trabalho. Consulte as seções seguintes para obter mais informações sobre pnpm install
.
Esta seção rastreia a integridade do repositório e do processo de publicação. Pode ser útil para contribuidores que enfrentam problemas com seus PRs e pacotes.
Se algo aqui parecer errado ou alguma das opções acima estiver falhando, informe-nos no canal Definitely Typed no servidor TypeScript Community Discord.
Consulte o manual do TypeScript.
Este é o método preferido. Por exemplo:
npm install --save-dev @types/node
Para instalar tipificações para um módulo com escopo definido, remova o @
e adicione sublinhado duplo após o escopo. Por exemplo, para instalar tipificações para @babel/preset-env
:
npm install --save-dev @types/babel__preset-env
Os tipos devem então ser incluídos automaticamente pelo compilador. Talvez seja necessário adicionar uma referência types
se não estiver usando módulos:
/// <reference types="node" />
Veja mais no manual.
Para um pacote npm "foo", a digitação será em "@types/foo".
Se o seu pacote tiver tipificações especificadas usando a chave types
ou typings
em seu package.json
, o registro npm exibirá que o pacote tem ligações disponíveis da seguinte forma:
Você pode clonar o repositório inteiro normalmente, mas ele é grande e inclui um diretório enorme de pacotes do tipo. A clonagem levará algum tempo e pode ser desnecessariamente complicada.
Para um clone mais gerenciável que inclua apenas os pacotes de tipo relevantes para você, você pode usar os recursos sparse-checkout
e --filter
do git. Isso reduzirá o tempo de clonagem e melhorará o desempenho do git.
️ Isso requer no mínimo a versão 2.27.0 do git, que provavelmente é mais recente que o padrão na maioria das máquinas. Procedimentos mais complicados estão disponíveis em versões mais antigas, mas não são abordados neste guia.
git clone --sparse --filter=blob:none <forkedUrl>
--sparse
inicializa o arquivo sparse-checkout para que o diretório de trabalho comece apenas com os arquivos na raiz do repositório.--filter=blob:none
incluirá todo o histórico de commits, mas excluirá arquivos, buscando-os apenas quando necessário.git sparse-checkout add types/<type> types/<dependency-type> ...
pnpm test <package to test>
. Quando você faz um PR para editar um pacote existente, dt-bot
deve @mencionar os proprietários do pacote. Caso contrário, você mesmo pode fazê-lo no comentário associado ao PR.
Se você for o autor da biblioteca e seu pacote for escrito em TypeScript, agrupe os arquivos de declaração gerados em seu pacote em vez de publicar no Definitely Typed. Você também pode gerar arquivos de declaração a partir de arquivos JavaScript, usando JSDoc para anotações de tipo.
Se você estiver adicionando tipificações para um pacote npm, crie um diretório com o mesmo nome. Se o pacote para o qual você está adicionando digitações não estiver no npm, certifique-se de que o nome escolhido para ele não entre em conflito com o nome de um pacote no npm. (Você pode usar npm info <my-package>
para verificar a existência do pacote <my-package>
.)
Seu pacote deve ter esta estrutura:
Arquivo | Propósito |
---|---|
index.d.ts | Contém as tipificações do pacote. |
<my-package>-tests.ts | Contém código de exemplo que testa as digitações. Este código não é executado, mas é verificado por tipo. |
tsconfig.json | Isso permite que você execute tsc dentro do pacote. |
.eslintrc.json | (Raramente) Necessário apenas para desabilitar regras de lint escritas para eslint. |
package.json | Contém metadados do pacote, incluindo nome, versão e dependências. |
.npmignore | Especifica quais arquivos devem ser incluídos no pacote. |
Gere-os executando npx dts-gen --dt --name <my-package> --template module
. Veja todas as opções em dts-gen.
Se você tiver arquivos .d.ts
além de index.d.ts
, certifique-se de que eles sejam referenciados em index.d.ts
ou nos testes.
Os membros do Definitely Typed monitoram rotineiramente novos PRs, mas tenha em mente que o número de outros PRs pode retardar as coisas.
Para um bom exemplo de pacote, consulte base64-js.
Quando um pacote agrupa seus próprios tipos, os tipos devem ser removidos do Definitely Typed para evitar confusão.
Você pode removê-lo executando pnpm run not-needed <typingsPackageName> <asOfVersion> [<libraryName>]
.
<typingsPackageName>
: Este é o nome do diretório a ser excluído.<asOfVersion>
: Um stub será publicado em @types/<typingsPackageName>
com esta versão. Deve ser superior a qualquer versão publicada atualmente e deve ser uma versão de <libraryName>
no npm.<libraryName>
: Nome do pacote npm que substitui os tipos Definitely Typed. Geralmente é idêntico a <typingsPackageName>
; nesse caso, você pode omiti-lo. Se um pacote nunca esteve em Definitely Typed, ele não precisa ser adicionado a notNeededPackages.json
.
Teste suas alterações executando pnpm test <package to test>
onde <package to test>
é o nome do seu pacote. Você precisa executar isso no diretório DefinitelyTyped porque package.jsons individuais não definem scripts de teste.
Este script usa dtslint para executar o compilador TypeScript em seus arquivos dts.
Depois de ter todas as alterações prontas, use pnpm run test-all
para ver como suas alterações afetam outros módulos.
attw
) verificações dtslint inclui formato de módulo e verificações de configuração package.json
de @arethetypeswrong/cli. As verificações são executadas apenas se um pacote de implementação compatível com SemVer-major puder ser encontrado no npm para comparar com o pacote DefinitelyTyped. (Pacotes DefinitivamenteTyped marcados como nonNpm
em seu package.json
são ignorados.)
Muitos pacotes atualmente falham nas verificações attw
e precisam ser corrigidos. Para nos permitir fazer progressos incrementais, as verificações attw
com falha não falham na execução dtslint
quando o pacote está listado em failingPackages
em attw.json
, mas ainda serão relatados na saída pnpm test my-package
. Se você corrigir o pacote, remova-o de failingPackages
para que as verificações attw
possam começar a falhar nas execuções dtslint
.
Todos os problemas relatados pelo attw
possuem documentação vinculada na saída. Algumas regras básicas para ajudar a evitar problemas:
O package.json
no pacote DefinitelyTyped deve ter campos type
e exports
correspondentes se o pacote de implementação os usar em seu package.json
. Por exemplo, se uma implementação package.json
for semelhante a:
{
"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 "
}
}
}
então o DefinitelyTyped package.json
deve ser algo como:
{
"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 subcaminho exports
é refletido e cada arquivo JavaScript tem um arquivo de declaração correspondente com uma extensão de arquivo correspondente – um arquivo .d.ts
digita um arquivo .js
, não um arquivo .mjs
ou .cjs
!
Quando o pacote de implementação usa module.exports = ...
, o pacote DefinitelyTyped deve usar export =
, não export default
. (Como alternativa, se module.exports
for apenas um objeto de propriedades nomeadas, o pacote DefinitelyTyped poderá usar uma série de exportações nomeadas.) O obstáculo mais comum para corrigir esse problema é a confusão sobre como exportar tipos além da exportação primária. Por exemplo, suponha que esses tipos estejam usando export default
incorretamente:
export interface Options {
// ...
}
export default function doSomething ( options : Options ) : void ;
Alterar o export default
para export =
cria um erro:
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 corrigir isso, mova os tipos dentro de um namespace com o mesmo nome da função:
declare namespace doSomething {
export interface Options {
// ...
}
}
declare function doSomething ( options : doSomething . Options ) : void ;
export = doSomething ;
Se precisar de ajuda para resolver um problema, pergunte no canal DefinitelyTyped no servidor TypeScript Community Discord.
Se você estiver adicionando tipificações para um pacote npm, crie um diretório com o mesmo nome. Se o pacote para o qual você está adicionando digitações não estiver no npm, defina "nonNpm": true
no package.json
e certifique-se de que o nome escolhido para ele não entre em conflito com o nome de um pacote no npm. (Você pode usar npm info <my-package>
para verificar a existência do pacote <my-package>
.)
Em raras ocasiões, nonNpm
pode ser definido como "conflict"
, o que indica que existe um pacote no npm com o mesmo nome, mas os tipos entram em conflito intencionalmente com esse pacote. Isso pode ser verdade para pacotes que definem um ambiente como @types/node
ou para pacotes fictícios como aws-lambda
. Evite usar "conflict"
sempre que possível.
<my-package>-tests.ts
Deve haver um arquivo <my-package>-tests.ts
, que é considerado seu arquivo de teste, junto com quaisquer arquivos *.ts
que ele importa. Se você não vir nenhum arquivo de teste na pasta do módulo, crie um <my-package>-tests.ts
. Esses arquivos são usados para validar a API exportada dos arquivos *.d.ts
que são enviados como @types/<my-package>
. Eles próprios não enviam.
As alterações nos arquivos *.d.ts
devem incluir uma alteração no arquivo *.ts
correspondente que mostre a API que está sendo usada, para que alguém não quebre acidentalmente o código do qual você depende. Por exemplo, esta alteração em uma função em um arquivo .d.ts
adicionando um novo parâmetro a uma função:
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("//", { })
Se você está se perguntando por onde começar com o código de teste, os exemplos no README do pacote original são um ótimo lugar para começar.
Você pode validar suas alterações com npm test <package to test>
na raiz deste repositório, que leva em consideração os arquivos alterados.
Use $ExpectType
para afirmar que uma expressão é de um determinado tipo e @ts-expect-error
para afirmar que é um erro de compilação. Exemplos:
// $ExpectType void
f ( 1 ) ;
// @ts-expect-error
f ( "one" ) ;
Para obter mais detalhes, consulte o leia-me do dtslint.
.eslintrc.json
Se por algum motivo uma regra lint precisar ser desabilitada, desabilite-a para uma linha específica:
// eslint-disable-next-line no-const-enum
const enum Const {
One ,
}
const enum Enum { // eslint-disable-line no-const-enum
Two ,
}
Você ainda pode desabilitar regras com um .eslintrc.json, mas não deveria em novos pacotes. Desabilitar regras para todo o pacote dificulta a revisão.
tsconfig.json
tsconfig.json
deve ter noImplicitAny
, noImplicitThis
, strictNullChecks
e strictFunctionTypes
definidos como true
.
Você pode editar o tsconfig.json
para adicionar novos arquivos de teste, para adicionar "target": "es6"
(necessário para funções assíncronas), para adicionar a "lib"
ou para adicionar a opção do compilador "jsx"
.
esModuleInterop
/ allowSyntheticDefaultImports
DR: esModuleInterop
e allowSyntheticDefaultImports
não são permitidos em seu tsconfig.json
.
Estas opções tornam possível escrever uma importação padrão para uma exportação CJS, modelando a interoperabilidade integrada entre os módulos CJS e ES no Node e em alguns empacotadores 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" ;Como a validade em tempo de compilação da importação em
index.d.ts
depende de configurações de compilação específicas, que os usuários de seus tipos não herdam, usar esse padrão em DefinitelyTyped forçaria os usuários a alterar suas próprias configurações de compilação, o que pode estar incorreto para seu tempo de execução. Em vez disso, você deve escrever uma importação CJS para uma exportação CJS para garantir compatibilidade ampla e independente de configuração:// index.d.ts // CJS import, modeling `const Component = require("./component")` in JS import Component = require ( "./component" ) ;
package.json
Este arquivo é obrigatório e deve seguir este modelo:
{
"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"
}
]
}
Um package.json
especifica todas as dependências, incluindo outros pacotes @types
.
Você deve adicionar dependências não @types
à lista de dependências externas permitidas. Pikaday é um bom exemplo. Essas adições são aprovadas por um mantenedor, o que nos dá a chance de garantir que os pacotes @types
não dependam de pacotes maliciosos.
Se o pacote de implementação usar ESM e especificar "type": "module"
, você deverá modificar package.json para corresponder:
{
"type" : " module "
}
Isso também se aplica se o pacote de implementação tiver exports
em seu package.json.
Definitivamente Typed permite peerDependencies
em package.json
. As dependências de mesmo nível podem ajudar a evitar situações em que um gerenciador de pacotes instala inesperadamente versões muito novas ou mais de uma versão do mesmo pacote. No entanto, as dependências entre pares têm desvantagens; gerenciadores de pacotes diferem no tratamento de dependências de pares (por exemplo, yarn
não os instala automaticamente, npm
requer --legacy-peer-deps
para incompatibilidades). Como tal, os PRs que introduzem novas dependências entre pares requerem a aprovação do mantenedor e devem ser limitados a circunstâncias específicas.
Em geral, os pacotes de tipos só devem ter uma dependência de mesmo nível se o pacote upstream tiver uma dependência de mesmo nível no mesmo pacote (ou em seus tipos). Por exemplo, um pacote DT para um componente React pode especificar uma dependência de mesmo nível em @types/react@*
, pois o consumidor precisará instalar @types/react
para usar JSX em primeiro lugar. Se o consumidor instalar @types/react@16
em seu projeto, mas uma versão mais recente de @types/react
estiver disponível no npm, a dependência de peer pode ajudar o gerenciador de pacotes a escolher @types/react@16
em vez dessa versão mais recente. Da mesma forma, chai-as-promised
tem uma dependência de par em chai
, então @types/chai-as-promised
deve ter uma dependência de par em @types/chai
.
Existem alguns casos em que o pacote upstream não possui uma dependência de mesmo nível no pacote de tipos, mas uma dependência de mesmo nível ainda é apropriada. Normalmente, esses são casos em que o pacote upstream estende outro pacote e assume que ele existe, portanto deveria ter declarado uma dependência de mesmo nível ao estender outro pacote, mas não o fez. Por exemplo, chai-match-pattern
estende chai
, mas não declara uma dependência de mesmo nível em chai
, mas precisa dela para funcionar. @types/chai-match-pattern
deve ter uma dependência de mesmo nível em @types/chai
.
Se um pacote simplesmente expõe tipos de outro pacote como parte de sua API devido a uma dependência regular no pacote upstream, ele não deve usar uma dependência de mesmo nível. Por exemplo, express
possui qs
em suas "dependencies"
. Quando os usuários instalam express
, eles não precisam instalar manualmente qs
. Da mesma forma, @types/express
tem @types/qs
em suas "dependencies"
. Seria incorreto declarar @types/qs
como uma dependência de mesmo nível de @types/express
, pois isso exigiria que alguns consumidores downstream instalassem manualmente @types/qs
.
.npmignore
Este arquivo define quais arquivos serão incluídos em cada pacote @types
. Deve assumir uma forma específica. Para pacotes com apenas uma versão no repositório:
*
! ** / * .d.ts
! ** / * .d.cts
! ** / * .d.mts
! ** / * .d. * .ts
O que quer dizer "ignore todos os arquivos, mas não ignore nenhum arquivo de declaração". Para pacotes que possuem mais de uma versão no repositório, a versão "mais recente" (no nível superior) deve conter algo como:
*
! ** / * .d.ts
! ** / * .d.cts
! ** / * .d.mts
! ** / * .d. * .ts
/ v15 /
/ v16 /
/ v17 /
Que é igual ao .npmignore
anterior, mas ignorando cada um dos diretórios filhos versionados.
O CI falhará se este arquivo contiver o conteúdo errado e fornecer o valor pretendido. Não importa o que este arquivo contenha, o editor publicará apenas arquivos de declaração.
pnpm dprint fmt -- 'path/to/package/**/*.ts'
..vscode/settings.template.json
(ou equivalente para outros editores) para formatar ao salvar com a extensão dprint do VS Codefunction sum(nums: number[]): number
: Use ReadonlyArray
se uma função não grava em seus parâmetros.interface Foo { new(): Foo; }
: Isso define um tipo de objetos que podem ser novos. Você provavelmente deseja declare class Foo { constructor(); }
.const Class: { new(): IClass; }
: Prefira usar uma declaração de classe class Class { constructor(); }
em vez de uma constante nova.getMeAT<T>(): T
: Se um parâmetro de tipo não aparecer nos tipos de nenhum parâmetro, você realmente não tem uma função genérica, apenas uma asserção de tipo disfarçada. Prefira usar uma asserção de tipo real, por exemplo, getMeAT() as number
. Exemplo onde um parâmetro de tipo é aceitável: function id<T>(value: T): T;
. Exemplo onde não é aceitável: function parseJson<T>(json: string): T;
. Exceção: new Map<string, number>()
está OK.Function
e Object
quase nunca é uma boa ideia. Em 99% dos casos é possível especificar um tipo mais específico. Os exemplos são (x: number) => number
para funções e { x: number, y: number }
para objetos. Se não houver certeza sobre o tipo, any
é a escolha certa, não Object
. Se o único fato conhecido sobre o tipo é que é algum objeto, use o tipo object
, não Object
ou { [key: string]: any }
.var foo: string | any
: quando any
é usado em um tipo de união, o tipo resultante ainda é any
. Portanto, embora a parte string
dessa anotação de tipo possa parecer útil, na verdade ela não oferece nenhuma verificação adicional de tipo, simplesmente usando any
. Dependendo da intenção, alternativas aceitáveis poderiam ser any
, string
ou string | object
.DR: não modifique
.github/CODEOWNERS
, sempre modifique a lista de proprietários empackage.json
.
DT possui o conceito de “Proprietários de Definição”, que são pessoas que desejam manter a qualidade dos tipos de um determinado módulo.
Para se adicionar como proprietário da definição, modifique a matriz owners
em package.json
:
"owners" : [
{
"name" : " Some Person " ,
"githubUsername" : " somebody "
},
{
"name" : " Some Corp " ,
"url" : " https://example.org "
}
]
Observe que esta lista não é usada para fornecer crédito para contribuições; ele é usado apenas para gerenciar revisões de RP.
Uma vez por semana, os Proprietários da Definição são sincronizados com o arquivo .github/CODEOWNERS que é nossa fonte de verdade.
Definitivamente Typed é um dos repositórios mais ativos no GitHub. Você deve estar se perguntando como surgiu o projeto. @johnnyreilly escreveu uma história de Definitely Typed. Ele conta a história dos primeiros dias do Definitely Typed, desde um repositório criado por @borisyankov, até o ponto em que se tornou uma parte fundamental do ecossistema TypeScript. Você pode ler a história de Definitely Typed aqui.
@types
no npm? O branch master
é publicado automaticamente no escopo @types
no npm graças ao DefinitelyTyped-tools.
Depende, mas a maioria das solicitações pull serão mescladas dentro de uma semana. Alguns PRs podem ser mesclados pelos proprietários de um módulo e podem ser mesclados com muito mais rapidez. Aproximadamente:
PRs que alteram apenas os tipos de um módulo e possuem alterações de testes correspondentes serão mesclados muito mais rapidamente
PRs que foram aprovados por um proprietário listado no package.json
da definição geralmente são mesclados mais rapidamente; PRs para novas definições levarão mais tempo, pois exigem mais revisão por parte dos mantenedores. Cada PR é revisado por um membro da equipe TypeScript ou Definitely Typed antes de ser mesclado, portanto, seja paciente, pois fatores humanos podem causar atrasos. Verifique o novo quadro de status de solicitação pull para ver o progresso à medida que os mantenedores trabalham nos PRs abertos.
Para alterações em módulos muito populares, por exemplo, Node/Express/Jest, que têm muitos milhões de downloads por semana no npm, os requisitos para contribuições são um pouco maiores. As alterações nestes projetos podem ter efeitos enormes no ecossistema e, por isso, tratamos as alterações neles com muito cuidado. Esses módulos exigem a aprovação de um mantenedor do DT e suporte entusiástico dos proprietários do módulo. A barreira para passar pode ser bastante alta e muitas vezes os PRs podem ficar obsoletos porque não há um campeão. Se você descobrir que ninguém está se comprometendo, tente fazer com que seu PR tenha um foco menor.
@types
npm será atualizado?Os pacotes npm devem ser atualizados dentro de uma hora. Se já se passou mais de uma hora, mencione o número do PR no canal Definitely Typed no servidor TypeScript Community Discord e o mantenedor atual obterá o membro correto da equipe para investigar.
<reference types="" />
ou uma importação? Se o módulo que você está referenciando for um módulo (usa export
), use uma importação. Se o módulo que você está referenciando for um módulo de ambiente (usa declare module
) ou apenas declare globais, use <reference types="" />
.
tsconfig.json
que está faltando "noImplicitAny": true
, "noImplicitThis": true
ou "strictNullChecks": true
.Então eles estão errados e ainda não percebemos. Você pode ajudar enviando uma solicitação pull para corrigi-los.
Sim, usando dprint. Recomendamos usar uma extensão dprint para o seu editor.
Alternativamente, você pode ativar um gancho git que formatará seu código automaticamente. Execute pnpm run setup-hooks
. Então, quando você confirmar, o comando dprint fmt
será executado nos arquivos alterados. Se você aproveitar as vantagens do clone parcial, certifique-se de chamar git sparse-checkout add .husky
para verificar os ganchos do git antes de executar o script setup-hooks
.
As solicitações pull não exigem formatação correta para serem mescladas. Qualquer código não formatado será reformatado automaticamente após ser mesclado.
Se você for um usuário do VS Code, sugerimos copiar o arquivo
.vscode/settings.template.json
para.vscode/settings.json
. Esse modelo define a extensão dprint VS Code como o formatador padrão no repositório.
Aqui estão as definições atualmente solicitadas.
Se os tipos fizerem parte de um padrão da web, eles deverão ser contribuídos para TypeScript-DOM-lib-generator para que possam se tornar parte do padrão lib.dom.d.ts
.
Se não houver nenhum código fonte JavaScript, por exemplo, se você estiver escrevendo tipos auxiliares ou tipos para uma especificação, você mesmo deve publicar os tipos, não no Definitely Typed. Como se destinam a fornecer tipos para código JavaScript existente, os pacotes @types
não devem ser importados diretamente. Ou seja, você não deve criar um pacote Definitely Typed que deve ser usado como import type { ... } from "@types/foo"
. Você também não deve escrever import type { ... } from "foo"
quando não houver foo
instalado.
Isso é diferente de fornecer tipos para uma biblioteca JavaScript apenas de navegador ou tipos para um ambiente inteiro, como node, bun, et al. Lá, os tipos são resolvidos implicitamente ou usando /// <references types="foo" />
.
Alguns pacotes, como chai-http, exportam uma função.
Importando este módulo com uma importação no estilo ES6 no formato import * as foo from "foo";
leva ao erro:
erro TS2497: O módulo 'foo' é resolvido para uma entidade que não é de módulo e não pode ser importado usando esta construção.
Este erro pode ser suprimido mesclando a declaração da função com um namespace vazio de mesmo nome, mas esta prática é desencorajada. Esta é uma resposta do Stack Overflow comumente citada em relação a esse assunto.
É mais apropriado importar o módulo usando import foo = require("foo");
sintaxe. No entanto, se você quiser usar uma importação padrão como import foo from "foo";
você tem duas opções:
--allowSyntheticDefaultImports
se o tempo de execução do seu módulo suportar um esquema de interoperabilidade para módulos não ECMAScript, ou seja, se as importações padrão funcionarem em seu ambiente (por exemplo, Webpack, SystemJS, esm).--esModuleInterop
se quiser que o TypeScript cuide da interoperabilidade não ECMAScript (desde o TypeScript 2.7). export =
, mas prefiro usar importações padrão. Posso alterar export =
para export default
? Como na pergunta anterior, consulte o uso das opções do compilador --allowSyntheticDefaultImports
ou --esModuleInterop
.
Não altere a definição do tipo se ela estiver precisa. Para um pacote npm, export =
é preciso se node -p 'require("foo")'
funciona para importar um módulo e export default
é preciso se node -p 'require("foo").default'
funciona para importar um módulo .
Em seguida, você terá definido a versão mínima suportada especificando "minimumTypeScriptVersion": "XY"
em package.json
.
No entanto, se o seu projeto precisar manter tipos compatíveis com, digamos, 3.7 e superior, ao mesmo tempo que tipos compatíveis com 3.6 ou inferior, você precisará usar o recurso typesVersions
. Você pode encontrar uma explicação detalhada desse recurso na documentação oficial do TypeScript.
Aqui está um pequeno exemplo para você começar:
Você terá que adicionar typesVersions
a package.json
:
{
"private" : true ,
"types" : " index " ,
"typesVersions" : {
"<=3.6" : { "*" : [ " ts3.6/* " ] }
}
}
Crie o subdiretório mencionado no campo typesVersions
dentro do seu diretório de tipos ( ts3.6/
neste exemplo). ts3.6/
suportará TypeScript versões 3.6 e inferiores, então copie os tipos e testes existentes lá.
De volta à raiz do pacote, adicione os recursos do TypeScript 3.7 que deseja usar. Quando as pessoas instalam o pacote, o TypeScript 3.6 e inferior iniciará em ts3.6/index.d.ts
, enquanto o TypeScript 3.7 e superior iniciará em index.d.ts
.
Você pode ver o bluebird como exemplo.
Isso pode pertencer ao gerador TypeScript-DOM-lib. Veja as orientações lá. Se a norma ainda for um rascunho, ela pertence aqui. Use um nome que comece com dom-
e inclua um link para o padrão como o link "Projeto" em package.json
. Quando ele passar para o modo rascunho, podemos removê-lo do Definitely Typed e descontinuar o pacote @types
associado.
NOTA: A discussão nesta seção pressupõe familiaridade com versionamento semântico
Cada pacote Definitely Typed é versionado quando publicado no npm. O DefinitelyTyped-tools (a ferramenta que publica pacotes @types
para npm) definirá a versão do pacote de declaração usando o número de versão major.minor.9999
listado em package.json
. Por exemplo, aqui estão as primeiras linhas das declarações de tipo do Node para a versão 20.8.x
no momento da escrita:
{
"private" : true ,
"name" : " @types/node " ,
"version" : " 20.8.9999 "
}
Como a versão está listada como 20.8.9999
, a versão npm do pacote @types/node
também será 20.8.x
. Observe que a versão em package.json
deve conter apenas a versão major.minor
(por exemplo, 10.12
) seguida de .9999
. Isso ocorre porque apenas os números de lançamento principais e secundários estão alinhados entre os pacotes de biblioteca e os pacotes de declaração de tipo. (O .9999
serve para garantir que os pacotes @types
locais sejam sempre mais recentes durante o desenvolvimento local.) O número de versão do patch do pacote de declaração de tipo (por exemplo, .0
em 20.8.0
) é inicializado em zero por Definitely Typed e é incrementado a cada vez. um novo pacote @types/node
é publicado no npm para a mesma versão principal/secundária da biblioteca correspondente.
Às vezes, as versões do pacote de declaração de tipo e as versões do pacote de biblioteca podem ficar fora de sincronia. Abaixo estão alguns motivos comuns, em ordem de quanto eles incomodam os usuários de uma biblioteca. Apenas o último caso é tipicamente problemático.
@types
, então npm update
normalmente funcionará. ❗ Se você estiver atualizando declarações de tipo para uma biblioteca, sempre defina a versão major.minor
em package.json
para corresponder à versão da biblioteca que você está documentando! ❗
O versionamento semântico exige que as versões com alterações significativas aumentem o número da versão principal. Por exemplo, uma biblioteca que remove uma função exportada publicamente após seu lançamento 3.5.8
deve aumentar sua versão para 4.0.0
em seu próximo lançamento. Além disso, quando a versão 4.0.0
da biblioteca for lançada, seu pacote de declaração de tipo Definitely Typed também deverá ser atualizado para 4.0.0
, incluindo quaisquer alterações significativas na API da biblioteca.
Muitas bibliotecas têm uma grande base instalada de desenvolvedores (incluindo mantenedores de outros pacotes que usam essa biblioteca como dependência) que não migrarão imediatamente para uma nova versão que tenha alterações importantes, porque pode levar meses até que um mantenedor tenha tempo para reescrever código para se adaptar à nova versão. Enquanto isso, os usuários de versões antigas de bibliotecas ainda podem querer atualizar as declarações de tipo para versões mais antigas.
Se você pretende continuar atualizando a versão mais antiga das declarações de tipo de uma biblioteca, você pode criar uma nova subpasta (por exemplo, /v2/
) nomeada para a versão atual (que em breve será "antiga") e copiar os arquivos existentes da versão atual para ela .
Ao criar uma nova pasta de versão, certifique-se de que o campo version de package.json
foi atualizado; pnpm
resolverá automaticamente para este pacote versionado sempre que for necessário. Se outros pacotes no repositório precisarem depender desta nova versão, certifique-se de que seus package.json
s também estejam atualizados.
Por exemplo, se estivermos criando types/history/v2
, seu package.json
seria parecido com:
{
"private" : true ,
"name" : " @types/history " ,
"version" : " 2.4.9999 "
}
Outro pacote pode selecionar esta versão especificando:
{
"private" : true ,
"name" : " @types/browser-sync " ,
"version" : " 2.26.9999 " ,
"dependencies" : {
"@types/history" : " ^2 "
}
}
Além disso, /// <reference types=".." />
não funcionará com mapeamento de caminho, portanto, as dependências devem usar import
.
Os pacotes @types
sempre digitam pacotes da mesma versão, então @types/[email protected]
são para [email protected]
. Como consequência, todas as alterações, sejam elas quebradas ou não, são publicadas como revisões de patch, a menos que sejam combinadas com um aumento maior/menor para alterar a versão do pacote alvo (coincidentemente ou não).
Quando se trata de alterações significativas, os mantenedores do DT consideram a popularidade do pacote, as vantagens da alteração significativa proposta, o esforço que será necessário para os usuários corrigirem seu código e se a alteração poderia ser razoavelmente adiada até que possa ser sincronizada. com um grande impacto na biblioteca upstream.
O manual TypeScript contém excelentes informações gerais sobre como escrever definições e também este arquivo de definição de exemplo que mostra como criar uma definição usando a sintaxe de módulo no estilo ES6, ao mesmo tempo que especifica objetos disponibilizados para o escopo global. Essa técnica é demonstrada praticamente na definição de big.js
, que é uma biblioteca que pode ser carregada globalmente via tag de script em uma página da web ou importada via require ou importações no estilo ES6.
Para testar como sua definição pode ser usada quando referenciada globalmente ou como um módulo importado, crie uma pasta test
e coloque dois arquivos de teste nela. Nomeie um YourLibraryName-global.test.ts
e o outro YourLibraryName-module.test.ts
. O arquivo de teste global deve exercitar a definição de acordo com como seria utilizado em um script carregado em uma página web onde a biblioteca está disponível no escopo global - neste cenário você não deve especificar uma instrução de importação. O arquivo de teste do módulo deve exercitar a definição de acordo com como seria usado quando importado (incluindo a(s) instrução(ões) import
). Se você especificar uma propriedade files
no seu arquivo tsconfig.json
, inclua os dois arquivos de teste. Um exemplo prático disso também está disponível na definição big.js
Observe que não é necessário exercer completamente a definição em cada arquivo de teste - é suficiente testar apenas os elementos acessíveis globalmente no arquivo de teste global e exercer totalmente a definição no arquivo de teste do módulo ou vice -versa.
Os tipos de um pacote escopo @foo/bar
devem entrar em types/foo__bar
. Observe o sublinhado duplo.
Este projeto está licenciado sob a licença do MIT.
Os direitos autorais dos arquivos de definição são respectivos de cada colaborador listado no início de cada arquivo de definição.