Репозиторий высококачественных определений типов TypeScript.
Вы также можете прочитать этот README на испанском, 한국어, русском, 简体中文, португальском, итальянском, 日本語 и французском языках!
Ссылка на руководство администратора
Определенно типизированный недавно был заменен на полноценный монорепозиторий pnpm
; вы можете перечитать этот документ, чтобы узнать об изменениях в расположении пакетов в этом репозитории.
По крайней мере, вы можете захотеть выполнить git clean -fdx
репозиторий (или node ./scripts/clean-node-modules.js
в Windows), чтобы очистить node_modules
и запустить pnpm install --filter .
для установки корня рабочей области. Дополнительную информацию об pnpm install
смотрите в дальнейших разделах.
В этом разделе отслеживается состояние репозитория и процесс публикации. Это может быть полезно для участников, испытывающих какие-либо проблемы с их PR и пакетами.
Если что-то здесь кажется неправильным или что-то из вышеперечисленного не работает, сообщите нам об этом в канале Definitely Typed на сервере Discord сообщества TypeScript.
См. руководство по TypeScript.
Это предпочтительный метод. Например:
npm install --save-dev @types/node
Чтобы установить типизацию для модуля с заданной областью, удалите @
и добавьте двойное подчеркивание после области. Например, чтобы установить типизацию для @babel/preset-env
:
npm install --save-dev @types/babel__preset-env
Затем типы должны быть автоматически включены компилятором. Возможно, вам придется добавить ссылку на types
если вы не используете модули:
/// <reference types="node" />
Подробнее смотрите в справочнике.
Для пакета npm «foo» типизация будет по адресу «@types/foo».
Если в вашем пакете типизация указана с использованием ключа types
или typings
в его package.json
, реестр npm отобразит, что пакет имеет доступные привязки, например:
Вы можете клонировать весь репозиторий, как обычно, но он большой и включает в себя огромный каталог типовых пакетов. Клонирование займет некоторое время и может оказаться излишне громоздким.
Для более управляемого клона, включающего только те пакеты типов, которые вам нужны, вы можете использовать функции git sparse-checkout
и --filter
. Это сократит время клонирования и улучшит производительность git.
️ Для этого требуется git версии минимум 2.27.0, которая, вероятно, новее, чем версия по умолчанию на большинстве компьютеров. Более сложные процедуры доступны в более старых версиях, но не рассматриваются в этом руководстве.
git clone --sparse --filter=blob:none <forkedUrl>
--sparse
инициализирует файл разреженной проверки, поэтому рабочий каталог начинается только с файлов в корне репозитория.--filter=blob:none
будет включать всю историю коммитов, но исключать файлы, извлекая их только по мере необходимости.git sparse-checkout add types/<type> types/<dependency-type> ...
pnpm test <package to test>
. Когда вы делаете запрос на редактирование существующего пакета, dt-bot
должен @-упомянуть владельцев пакета. Если нет, то вы можете сделать это самостоятельно в комментарии, связанном с пиаром.
Если вы являетесь автором библиотеки и ваш пакет написан на TypeScript, объедините сгенерированные файлы объявлений в свой пакет вместо публикации в Definitely Typed. Вы также можете создавать файлы объявлений из файлов JavaScript, используя JSDoc для аннотаций типов.
Если вы добавляете типизацию для пакета npm, создайте каталог с тем же именем. Если пакета, для которого вы добавляете типизацию, нет в npm, убедитесь, что выбранное вами имя не конфликтует с именем пакета в npm. (Вы можете использовать npm info <my-package>
, чтобы проверить существование пакета <my-package>
.)
Ваш пакет должен иметь следующую структуру:
Файл | Цель |
---|---|
index.d.ts | Он содержит типизацию для пакета. |
<my-package>-tests.ts | Он содержит пример кода, который проверяет типизацию. Этот код не запускается, но его тип проверяется. |
tsconfig.json | Это позволяет вам запускать tsc внутри пакета. |
.eslintrc.json | (Редко) Требуется только для отключения правил lint, написанных для eslint. |
package.json | Содержит метаданные пакета, включая его имя, версию и зависимости. |
.npmignore | Указывает, какие файлы планируется включить в пакет. |
Создайте их, запустив npx dts-gen --dt --name <my-package> --template module
. Посмотрите все варианты на dts-gen.
Если у вас есть файлы .d.ts
помимо index.d.ts
, убедитесь, что на них есть ссылки либо в index.d.ts
, либо в тестах.
Члены Definitely Typed регулярно отслеживают новые PR, однако имейте в виду, что количество других PR может замедлить ход процесса.
Хороший пример пакета см. в разделе base64-js.
Когда пакет объединяет свои собственные типы, типы следует удалить из Определенно типизированные, чтобы избежать путаницы.
Вы можете удалить его, запустив pnpm run not-needed <typingsPackageName> <asOfVersion> [<libraryName>]
.
<typingsPackageName>
: это имя каталога, который нужно удалить.<asOfVersion>
: заглушка будет опубликована в @types/<typingsPackageName>
с этой версией. Должна быть выше любой опубликованной в настоящее время версии и должна быть версией <libraryName>
в npm.<libraryName>
: имя пакета npm, который заменяет определенно типизированные типы. Обычно это идентично <typingsPackageName>
, и в этом случае его можно опустить. Если пакет никогда не был в состоянии Определенно типизирован, его не нужно добавлять в notNeededPackages.json
.
Проверьте свои изменения, запустив pnpm test <package to test>
где <package to test>
— это имя вашего пакета. Вам необходимо запустить его из каталога DefinitelyTyped, поскольку отдельные файлы package.json не определяют тестовые сценарии.
Этот сценарий использует dtslint для запуска компилятора TypeScript для ваших файлов dts.
Когда все изменения будут готовы, используйте pnpm run test-all
чтобы увидеть, как ваши изменения повлияют на другие модули.
attw
) проверяет dtslint включает проверку формата модуля и конфигурации package.json
из @arethetypeswrong/cli. Проверки выполняются только в том случае, если пакет реализации, совместимый с SemVer-major, можно найти в npm для сравнения с пакетом DefinitelyTyped. (Пакеты с определенным типом, помеченные как nonNpm
в их package.json
пропускаются.)
Многие пакеты в настоящее время не проходят проверку attw
, и их необходимо исправить. Чтобы мы могли добиться постепенного прогресса, неудачные проверки attw
не приводят к сбою запуска dtslint
, когда пакет указан в failingPackages
в attw.json
, но о них все равно будет сообщено в выходных данных pnpm test my-package
. Если вы исправите пакет, удалите его из failingPackages
, чтобы проверки attw
могли начать сбой при запуске dtslint
.
Все проблемы, о которых сообщает attw
имеют связанную с ними документацию. Несколько правил, которые помогут избежать проблем:
package.json
в пакете DefinitelyTyped должен иметь соответствующий type
и поля exports
, если пакет реализации использует их в своем package.json
. Например, если реализация package.json
выглядит так:
{
"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 "
}
}
}
тогда package.json
DefinitelyTyped.json должен выглядеть примерно так:
{
"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"
}
}
}
Обратите внимание, что каждый подпуть exports
отображается, и каждый файл JavaScript имеет соответствующий файл объявления с соответствующим расширением файла — файл .d.ts
является файлом .js
, а не файлом .mjs
или .cjs
!
Когда пакет реализации использует module.exports = ...
, пакет DefinitelyTyped должен использовать export =
, а не export default
. (В качестве альтернативы, если module.exports
является просто объектом именованных свойств, пакет DefinitelyTyped может использовать серию именованных экспортов.) Наиболее распространенным препятствием для решения этой проблемы является путаница в том, как экспортировать типы в дополнение к основному экспорту. Например, предположим, что эти типы неправильно используют export default
:
export interface Options {
// ...
}
export default function doSomething ( options : Options ) : void ;
Изменение export default
на export =
приводит к ошибке:
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.
Чтобы исправить это, переместите типы внутри пространства имен с тем же именем, что и у функции:
declare namespace doSomething {
export interface Options {
// ...
}
}
declare function doSomething ( options : doSomething . Options ) : void ;
export = doSomething ;
Если вам нужна помощь в решении проблемы, обратитесь в канал DefinitelyTyped на сервере Discord сообщества TypeScript.
Если вы добавляете типизацию для пакета npm, создайте каталог с тем же именем. Если пакет, для которого вы добавляете типизацию, отсутствует в npm, установите "nonNpm": true
в package.json
и убедитесь, что выбранное вами имя не конфликтует с именем пакета в npm. (Вы можете использовать npm info <my-package>
, чтобы проверить существование пакета <my-package>
.)
В редких случаях nonNpm
может быть установлено значение "conflict"
, что означает, что в npm существует пакет с таким же именем, но типы намеренно конфликтуют с этим пакетом. Это может быть справедливо для пакетов, которые определяют среду, например @types/node
или для фиктивных пакетов, таких как aws-lambda
. По возможности избегайте использования "conflict"
.
<my-package>-tests.ts
Должен существовать файл <my-package>-tests.ts
, который считается вашим тестовым файлом, а также все файлы *.ts
которые он импортирует. Если вы не видите тестовых файлов в папке модуля, создайте <my-package>-tests.ts
. Эти файлы используются для проверки API, экспортированного из файлов *.d.ts
, которые поставляются как @types/<my-package>
. Сами они не отправляют.
Изменения в файлах *.d.ts
должны включать соответствующее изменение файла *.ts
, показывающее используемый API, чтобы кто-то случайно не сломал код, от которого вы зависите. Например, это изменение функции в файле .d.ts
, добавляющее в функцию новый параметр:
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("//", { })
Если вам интересно, с чего начать тестовый код, примеры в README исходного пакета — отличное место для начала.
Вы можете проверить свои изменения с помощью npm test <package to test>
из корня этого репозитория, который учитывает измененные файлы.
Используйте $ExpectType
, чтобы подтвердить, что выражение имеет заданный тип, и @ts-expect-error
чтобы подтвердить, что произошла ошибка компиляции. Примеры:
// $ExpectType void
f ( 1 ) ;
// @ts-expect-error
f ( "one" ) ;
Дополнительные сведения см. в файле сведений о dtslint.
.eslintrc.json
Если по какой-то причине правило lint необходимо отключить, отключите его для конкретной строки:
// eslint-disable-next-line no-const-enum
const enum Const {
One ,
}
const enum Enum { // eslint-disable-line no-const-enum
Two ,
}
Вы по-прежнему можете отключить правила с помощью .eslintrc.json, но не следует этого делать в новых пакетах. Отключение правил для всего пакета усложняет проверку.
tsconfig.json
tsconfig.json
для noImplicitAny
, noImplicitThis
, strictNullChecks
и strictFunctionTypes
должно быть установлено значение true
.
Вы можете отредактировать tsconfig.json
, чтобы добавить новые тестовые файлы, добавить "target": "es6"
(необходим для асинхронных функций), добавить в "lib"
или добавить параметр компилятора "jsx"
.
esModuleInterop
/ allowSyntheticDefaultImports
TL;DR: esModuleInterop
allowSyntheticDefaultImports
не разрешены в вашем tsconfig.json
.
Эти параметры позволяют написать импорт по умолчанию для экспорта CJS, моделируя встроенную совместимость между модулями CJS и ES в Node и в некоторых сборщиках 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" ;Поскольку допустимость импорта в
index.d.ts
во время компиляции зависит от конкретных параметров компиляции, которые пользователи ваших типов не наследуют, использование этого шаблона в DefinitelyTyped заставит пользователей изменить свои собственные параметры компиляции, что может быть неверным. для времени их выполнения. Вместо этого вы должны написать импорт CJS для экспорта CJS, чтобы обеспечить широкую, независимую от конфигурации совместимость:// index.d.ts // CJS import, modeling `const Component = require("./component")` in JS import Component = require ( "./component" ) ;
package.json
Этот файл является обязательным и должен соответствовать этому шаблону:
{
"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"
}
]
}
В package.json
указаны все зависимости, включая другие пакеты @types
.
Вы должны добавить зависимости, отличные от @types
, в список разрешенных внешних зависимостей. Пикадей — хороший пример. Эти дополнения одобрены сопровождающим, что дает нам возможность убедиться, что пакеты @types
не зависят от вредоносных пакетов.
Если пакет реализации использует ESM и указывает "type": "module"
, вам следует изменить package.json так, чтобы он соответствовал:
{
"type" : " module "
}
Это также применимо, если пакет реализации имеет exports
в package.json.
Определенно типизированный позволяет использовать peerDependencies
в package.json
. Одноранговые зависимости могут помочь предотвратить ситуации, когда менеджер пакетов неожиданно устанавливает слишком новые версии или несколько версий одного и того же пакета. Однако у одноранговых зависимостей есть свои недостатки; Менеджеры пакетов различаются по обработке одноранговых зависимостей (например, yarn
не устанавливает их автоматически, npm
требует --legacy-peer-deps
для несоответствий). Таким образом, PR, вводящие новые зависимости от одноранговых узлов, требуют одобрения сопровождающего и должны быть ограничены конкретными обстоятельствами.
В общем, пакеты типов должны иметь одноранговую зависимость только в том случае, если вышестоящий пакет имеет одноранговую зависимость от того же пакета (или его типов). Например, пакет DT для компонента React может указать одноранговую зависимость от @types/react@*
, поскольку потребителю сначала потребуется установить @types/react
для использования JSX. Если потребитель устанавливает @types/react@16
в свой проект, но более новая версия @types/react
доступна в npm, зависимость от однорангового узла может помочь менеджеру пакетов выбрать @types/react@16
вместо этой более новой версии. Аналогично, chai-as-promised
имеет одноранговую зависимость от chai
, поэтому @types/chai-as-promised
должен иметь одноранговую зависимость от @types/chai
.
В некоторых случаях вышестоящий пакет не имеет одноранговой зависимости от пакета типов, но зависимость от однорангового узла по-прежнему уместна. Обычно это случаи, когда вышестоящий пакет расширяет другой пакет и предполагает, что он существует, поэтому должен был объявить одноранговую зависимость, поскольку он расширяет другой пакет, но не сделал этого. Например, chai-match-pattern
расширяет chai
, но не объявляет одноранговую зависимость от chai
, но требует, чтобы он функционировал. @types/chai-match-pattern
должен иметь одноранговую зависимость от @types/chai
.
Если пакет просто предоставляет типы из другого пакета как часть своего API из-за регулярной зависимости в вышестоящем пакете, ему не следует использовать одноранговую зависимость. Например, express
имеет qs
в своих "dependencies"
. Когда пользователи устанавливают express
, им не нужно вручную устанавливать qs
. Аналогично, @types/express
имеет @types/qs
в своих "dependencies"
. Было бы неправильно объявлять @types/qs
одноранговой зависимостью @types/express
, поскольку для этого некоторым нижестоящим потребителям потребуется вручную установить @types/qs
.
.npmignore
Этот файл определяет, какие файлы должны быть включены в каждый пакет @types
. Оно должно принять определенную форму. Для пакетов, имеющих только одну версию в репозитории:
*
! ** / * .d.ts
! ** / * .d.cts
! ** / * .d.mts
! ** / * .d. * .ts
То есть «игнорировать все файлы, но не игнорировать файлы объявлений». Для пакетов, имеющих более одной версии в репозитории, «последняя» версия (на верхнем уровне) должна содержать что-то вроде:
*
! ** / * .d.ts
! ** / * .d.cts
! ** / * .d.mts
! ** / * .d. * .ts
/ v15 /
/ v16 /
/ v17 /
Это то же самое, что и предыдущий .npmignore
, но игнорирует каждый из дочерних каталогов, имеющих версии.
CI завершится сбоем, если этот файл содержит неправильное содержимое и предоставит заданное значение. Независимо от того, что содержит этот файл, издатель будет публиковать только файлы деклараций.
pnpm dprint fmt -- 'path/to/package/**/*.ts'
..vscode/settings.template.json
(или эквивалента для других редакторов) для форматирования при сохранении с расширением VS Code dprint.function sum(nums: number[]): number
: используйте ReadonlyArray
, если функция не записывает в свои параметры.interface Foo { new(): Foo; }
: определяет тип новых объектов. Вероятно, вы захотите declare class Foo { constructor(); }
.const Class: { new(): IClass; }
: Предпочитаю использовать объявление класса class Class { constructor(); }
вместо новой константы.getMeAT<T>(): T
: Если параметр типа не отображается в типах каких-либо параметров, на самом деле у вас нет универсальной функции, у вас просто есть замаскированное утверждение типа. Предпочитайте использовать утверждение реального типа, например getMeAT() as number
. Пример допустимого параметра типа: function id<T>(value: T): T;
. Пример, где это неприемлемо: function parseJson<T>(json: string): T;
. Исключение: new Map<string, number>()
в порядке.Function
и Object
почти никогда не является хорошей идеей. В 99% случаев можно указать более конкретный тип. Примеры: (x: number) => number
для функций и { x: number, y: number }
для объектов. Если нет никакой уверенности в выборе типа, правильным выбором будет any
, а не Object
. Если единственный известный факт о типе — это то, что это какой-то объект, используйте тип object
, а не Object
или { [key: string]: any }
.var foo: string | any
: если в типе объединения используется any
, результирующим типом по-прежнему будет any
. Таким образом, хотя string
часть этой аннотации типа может выглядеть полезной, на самом деле она не предлагает никакой дополнительной проверки типов по сравнению с простым использованием any
. В зависимости от намерения приемлемыми альтернативами могут быть any
, string
или string | object
.TL;DR: не изменяйте
.github/CODEOWNERS
, всегда изменяйте список владельцев вpackage.json
.
В DT есть концепция «владельцев определений», то есть людей, которые хотят поддерживать качество определенных типов модулей.
Чтобы добавить себя в качестве владельца определения, измените массив owners
в package.json
:
"owners" : [
{
"name" : " Some Person " ,
"githubUsername" : " somebody "
},
{
"name" : " Some Corp " ,
"url" : " https://example.org "
}
]
Обратите внимание, что этот список не используется для зачета взносов; он используется только для управления PR-обзорами.
Раз в неделю владельцы определений синхронизируются с файлом .github/CODEOWNERS, который является нашим источником истины.
Definitely Typed — один из самых активных репозиториев на GitHub. Вы, возможно, задавались вопросом, как появился этот проект. @johnnyreilly написал историю Definitely Typed. В нем рассказывается история первых дней существования Definitely Typed, от репозитория, созданного @borisyankov, до момента, когда он стал ключевой частью экосистемы TypeScript. Историю Definitely Typed можно прочитать здесь.
@types
в npm? master
ветка автоматически публикуется в области @types
в npm благодаря DefinitelyTyped-tools.
Это зависит от ситуации, но большинство запросов на включение будут объединены в течение недели. Некоторые PR могут быть объединены владельцами модуля, и они могут быть объединены гораздо быстрее. Грубо:
PR, которые меняют только типы модулей и имеют соответствующие изменения тестов, будут объединены гораздо быстрее.
PR, одобренные владельцем, указанным в package.json
определения, обычно объединяются быстрее; PR для новых определений займет больше времени, поскольку они требуют более тщательного рассмотрения со стороны сопровождающих. Перед объединением каждый запрос на запрос проверяется членом команды TypeScript или Definitely Typed, поэтому проявите терпение, поскольку человеческий фактор может вызвать задержки. Посетите панель статуса новых запросов на включение, чтобы увидеть прогресс в работе сопровождающих по открытым запросам на включение.
Для изменений в очень популярных модулях, например Node/Express/Jest, которые каждую неделю загружаются миллионами раз в npm, требования к участию немного выше. Изменения в этих проектах могут иметь огромные последствия для экосистемы, поэтому мы относимся к ним с большой осторожностью. Эти модули требуют как одобрения специалиста по сопровождению DT, так и активной поддержки со стороны владельцев модулей. Планка прохождения этого этапа может быть довольно высокой, и часто личный рекорд может устареть, потому что у него нет чемпиона. Если вы обнаружите, что никто не берет на себя никаких обязательств, постарайтесь сделать ваш пиар менее фокусным.
@types
npm?Пакеты npm должны обновиться в течение часа. Если прошло больше часа, укажите номер PR на канале Definitely Typed на сервере Discord сообщества TypeScript, и текущий сопровождающий направит нужного члена команды для расследования.
<reference types="" />
или импорт? Если модуль, на который вы ссылаетесь, является модулем (использует export
), используйте импорт. Если модуль, на который вы ссылаетесь, является внешним модулем (использует declare module
) или просто объявляет глобальные переменные, используйте <reference types="" />
.
tsconfig.json
отсутствуют "noImplicitAny": true
, "noImplicitThis": true
или "strictNullChecks": true
.Тогда они ошибаются, а мы этого еще не заметили. Вы можете помочь, отправив запрос на включение, чтобы исправить их.
Да, с помощью dprint. Мы рекомендуем использовать расширение dprint для вашего редактора.
Альтернативно вы можете включить перехватчик git, который будет автоматически форматировать ваш код. Запустите pnpm run setup-hooks
. Затем, когда вы зафиксируете изменения, команда dprint fmt
будет выполнена для измененных файлов. Если вы воспользуетесь частичным клонированием, обязательно вызовите git sparse-checkout add .husky
, чтобы проверить перехватчики git, прежде чем запускать сценарий setup-hooks
.
Запросы на включение не требуют правильного форматирования для объединения. Любой неформатированный код будет автоматически переформатирован после объединения.
Если вы являетесь пользователем VS Code, мы предлагаем скопировать файл
.vscode/settings.template.json
в.vscode/settings.json
. Этот шаблон устанавливает расширение dprint VS Code в качестве средства форматирования по умолчанию в репозитории.
Вот запрошенные на данный момент определения.
Если типы являются частью веб-стандарта, их следует добавить в TypeScript-DOM-lib-generator, чтобы они могли стать частью lib.dom.d.ts
по умолчанию.
Если исходного кода JavaScript вообще нет, например, если вы пишете вспомогательные типы или типы для спецификации, вам следует публиковать типы самостоятельно, а не на сайте Definitely Typed. Поскольку пакеты @types
предназначены для предоставления типов для существующего кода JavaScript, их нельзя импортировать напрямую. То есть вам не следует создавать пакет с определенной типизацией, который предназначен для использования как import type { ... } from "@types/foo"
. Вам также не следует рассчитывать на запись import type { ... } from "foo"
если foo
не установлен.
Это отличается от предоставления типов для библиотеки JavaScript только для браузера или типов для всей среды, таких как node, Bun и т. д. Там типы либо разрешаются неявно, либо с помощью /// <references types="foo" />
.
Некоторые пакеты, например chai-http, экспортируют функцию.
Импорт этого модуля с помощью импорта в стиле ES6 в форме import * as foo from "foo";
приводит к ошибке:
ошибка TS2497: модуль «foo» разрешается в немодульный объект и не может быть импортирован с помощью этой конструкции.
Эту ошибку можно устранить, объединив объявление функции с пустым пространством имен с тем же именем, но такая практика не рекомендуется. Это часто цитируемый ответ на вопрос «Переполнение стека».
Более целесообразно импортировать модуль с помощью команды import foo = require("foo");
синтаксис. Тем не менее, если вы хотите использовать импорт по умолчанию, например, import foo from "foo";
у вас есть два варианта:
--allowSyntheticDefaultImports
, если среда выполнения вашего модуля поддерживает схему взаимодействия для модулей, отличных от ECMAScript, т. е. если импорт по умолчанию работает в вашей среде (например, Webpack, SystemJS, esm).--esModuleInterop
, если хотите, чтобы TypeScript заботился о взаимодействии, отличном от ECMAScript (начиная с TypeScript 2.7). export =
, но я предпочитаю использовать импорт по умолчанию. Могу ли я изменить export =
на export default
? Как и в предыдущем вопросе, обратитесь к использованию параметров компилятора --allowSyntheticDefaultImports
или --esModuleInterop
.
Не меняйте определение типа, если оно верно. Для пакета npm export =
является точным, если node -p 'require("foo")'
работает для импорта модуля, а export default
является точным, если node -p 'require("foo").default'
работает для импорта модуля .
Затем вы установите минимальную поддерживаемую версию, указав "minimumTypeScriptVersion": "XY"
в package.json
.
Однако если вашему проекту необходимо поддерживать типы, совместимые, скажем, с версией 3.7 и выше , одновременно с типами, совместимыми с версией 3.6 или ниже, вам потребуется использовать функцию typesVersions
. Подробное объяснение этой функции можно найти в официальной документации TypeScript.
Вот краткий пример для начала:
Вам нужно будет добавить typesVersions
в package.json
:
{
"private" : true ,
"types" : " index " ,
"typesVersions" : {
"<=3.6" : { "*" : [ " ts3.6/* " ] }
}
}
Создайте подкаталог, указанный в поле typesVersions
внутри вашего каталога типов (в этом примере ts3.6/
). ts3.6/
будет поддерживать TypeScript версии 3.6 и ниже, поэтому скопируйте туда существующие типы и тесты.
Вернитесь в корень пакета и добавьте функции TypeScript 3.7, которые вы хотите использовать. Когда люди устанавливают пакет, TypeScript 3.6 и ниже начинается с ts3.6/index.d.ts
, тогда как TypeScript 3.7 и выше начинается с index.d.ts
.
В качестве примера вы можете посмотреть bluebird.
Это может принадлежать TypeScript-DOM-lib-generator. Посмотрите рекомендации там. Если стандарт все еще является черновиком, ему место здесь. Используйте имя, начинающееся с dom-
и включите ссылку на стандарт в виде ссылки «Проект» в package.json
. Когда он выйдет из режима черновика, мы можем удалить его из «Определенно типизированного» и объявить устаревшим связанный пакет @types
.
ПРИМЕЧАНИЕ. Обсуждение в этом разделе предполагает знакомство с семантическим управлением версиями.
Для каждого определенно типизированного пакета создается версия при публикации в npm. Инструменты DefinitelyTyped (инструмент, который публикует пакеты @types
в npm) установит версию пакета объявления, используя номер версии major.minor.9999
, указанный в package.json
. Например, вот первые несколько строк объявлений типов Node для версии 20.8.x
на момент написания:
{
"private" : true ,
"name" : " @types/node " ,
"version" : " 20.8.9999 "
}
Поскольку версия указана как 20.8.9999
, версия npm пакета @types/node
также будет 20.8.x
Обратите внимание, что версия в package.json
должна содержать только версию major.minor
(например, 10.12
), за которой следует .9999
. Это связано с тем, что между пакетами библиотек и пакетами объявлений типов совпадают только основные и второстепенные номера выпусков. (Значение .9999
предназначено для обеспечения того, чтобы локальные пакеты @types
всегда были новейшими во время локальной разработки.) Номер версии исправления пакета объявления типа (например, .0
в 20.8.0
) инициализируется нулем с помощью Definitely Typed и увеличивается каждый раз. новый пакет @types/node
публикуется в npm для той же основной/вспомогательной версии соответствующей библиотеки.
Иногда версии пакета объявления типа и версии пакета библиотеки могут не синхронизироваться. Ниже приведены несколько распространенных причин, в порядке того, насколько они доставляют неудобства пользователям библиотеки. Только последний случай обычно проблематичен.
@types
соответствуют, то npm update
обычно должно работать. ❗ Если вы обновляете объявления типов для библиотеки, всегда устанавливайте версию major.minor
в package.json
чтобы она соответствовала версии библиотеки, которую вы документируете! ❗
Семантическое управление версиями требует, чтобы версии с критическими изменениями увеличивали основной номер версии. Например, библиотека, которая удаляет публично экспортированную функцию после выпуска 3.5.8
, должна повысить свою версию до 4.0.0
в следующем выпуске. Кроме того, когда выйдет версия библиотеки 4.0.0
, пакет объявления типа Definitely Typed также должен быть обновлен до 4.0.0
, включая любые критические изменения в API библиотеки.
Многие библиотеки имеют большую базу разработчиков (включая сопровождающих других пакетов, использующих эту библиотеку в качестве зависимости), которые не будут сразу переходить к новой версии, содержащей критические изменения, потому что могут пройти месяцы, прежде чем сопровождающий найдет время переписать. код для адаптации к новой версии. Тем временем пользователи старых версий библиотек все еще могут захотеть обновить объявления типов для более старых версий.
Если вы намерены продолжать обновлять старую версию объявлений типов библиотеки, вы можете создать новую подпапку (например /v2/
), названную в честь текущей версии (которая вскоре станет «старой»), и скопировать в нее существующие файлы из текущей версии. .
При создании папки новой версии убедитесь, что поле версии package.json
обновлено; pnpm
автоматически преобразует этот версионный пакет всякий раз, когда это необходимо. Если другие пакеты в репозитории должны зависеть от этой новой версии, убедитесь, что их package.json
также обновлены.
Например, если мы создаем types/history/v2
, его package.json
будет выглядеть так:
{
"private" : true ,
"name" : " @types/history " ,
"version" : " 2.4.9999 "
}
Другой пакет может выбрать эту версию, указав:
{
"private" : true ,
"name" : " @types/browser-sync " ,
"version" : " 2.26.9999 " ,
"dependencies" : {
"@types/history" : " ^2 "
}
}
Кроме того, /// <reference types=".." />
не будет работать с сопоставлением путей, поэтому зависимости должны использовать import
.
Пакеты @types
всегда типизируют пакеты одной и той же версии, поэтому @types/[email protected]
относятся к [email protected]
. Как следствие, все изменения, критические или нет, публикуются как исправления, если только они не сопровождаются значительным/незначительным изменением целевой версии пакета (случайно или нет).
Когда дело доходит до критических изменений, специалисты по сопровождению DT учитывают популярность пакета, преимущества предлагаемого критического изменения, усилия, которые потребуются пользователям для исправления своего кода, а также то, можно ли разумно отложить изменение до тех пор, пока оно не будет синхронизировано. с серьезным ударом вышестоящей библиотеки.
Руководство по TypeScript содержит отличную общую информацию о написании определений, а также этот пример файла определения, в котором показано, как создать определение с использованием синтаксиса модуля в стиле ES6, а также указать объекты, доступные в глобальной области видимости. Этот метод практически продемонстрирован в определении big.js
— библиотеки, которую можно загрузить глобально с помощью тега сценария на веб-странице или импортировать с помощью require или импорта в стиле ES6.
Чтобы проверить, как ваше определение может использоваться как при глобальной ссылке, так и в качестве импортированного модуля, создайте test
папку и поместите туда два тестовых файла. Назовите один YourLibraryName-global.test.ts
и другой YourLibraryName-module.test.ts
. Глобальный тестовый файл должен использовать определение в соответствии с тем, как он будет использоваться в сценарии, загруженном на веб-страницу, где библиотека доступна в глобальной области — в этом сценарии не следует указывать оператор импорта. Тестовый файл модуля должен использовать определение в соответствии с тем, как он будет использоваться при импорте (включая оператор(ы) import
). Если вы указали свойство files
в вашем файле tsconfig.json
, обязательно включите оба тестовых файла. Практический пример этого также доступен в определении big.js
Обратите внимание, что не требуется полностью использовать определение в каждом испытательном файле - достаточно проверить только глобально доступные элементы в глобальном тестовом файле и полностью использовать определение в файле тестирования модуля или наоборот.
Типы для пакета Scoped @foo/bar
должны перейти в types/foo__bar
. Обратите внимание на двойное подчеркивание.
Этот проект лицензируется по лицензии MIT.
Авторские права на файлы определения соответствуют каждому участнику, указанному в начале каждого файла определения.