Professional Documents
Culture Documents
smith / DefinitelyTyped
forked from DefinitelyTyped/DefinitelyTyped
Star
Watch
Code
Pull requests
Actions
Projects
Security
Insights
master
Go to file
View code
README.md
DefinitelyTyped
The repository for high quality TypeScript type definitions.
Also see the definitelytyped.org website, although information in this README is more up-to-date.
You can also read this README in Spanish, Korean, and Russian!
Current status
This section tracks the health of the repository and publishing process. It may be helpful for contributors experiencing
any issues with their PRs and packages.
All packages are type-checking/linting cleanly: build passing
All packages are being published to npm in under an hour: Azure Pipelines set up now
typescript-bot has been active on DefinitelyTyped Azure Pipelines set up now
If anything here seems wrong, or any of the above are failing, please raise an issue in the DefinitelyTyped Gitter channel.
gitter join chat
The types should then be automatically included by the compiler. See more in the handbook.
For an NPM package "foo", typings for it will be at "@types/foo". If you can't find your package, look for it on
TypeSearch.
If you still can't find it, check if it bundles its own typings. This is usually provided in a "types" or "typings" field in
the package.json , or just look for any ".d.ts" files in the package and manually include them with a /// <reference
path="" /> .
Other methods
These can be used by TypeScript 1.0.
Typings
NuGet (use preferred alternatives, nuget DT type publishing has been turned off)
Manually download from the master branch of this repository
You may need to add manual references.
Test
Before you share your improvement with the world, use it yourself.
(You can also use src/types .) Create types/foo/index.d.ts containing declarations for the module "foo". You
should now be able import from "foo" in your code and it will route to the new type definition. Then build and run the
code to make sure your type definition actually corresponds to what happens at runtime. Once you've tested your
definitions with real code, make a PR then follow the instructions to edit an existing package or create a new package.
If there is a tslint.json , run npm run lint package-name . Otherwise, run tsc in the package directory.
When you make a PR to edit an existing package, dt-bot should @-mention previous authors. If it doesn't, you can do
so yourself in the comment associated with the PR.
File Purpose
index.d.ts This contains the typings for the package.
foo-tests.ts This contains sample code which tests the typings. This code does not run, but it is type-checked.
tsconfig.json This allows you to run tsc within the package.
tslint.json Enables linting.
Generate these by running npx dts-gen --dt --name my-package-name --template module if you have npm ≥ 5.2.0,
npm install -g dts-gen and dts-gen --dt --name my-package-name --template module otherwise. See all
options at dts-gen.
You may edit the tsconfig.json to add new files, to add "target": "es6" (needed for async functions), to add to
"lib" , or to add the "jsx" compiler option.
DefinitelyTyped members routinely monitor for new PRs, though keep in mind that the number of other PRs may slow
things down.
For a good example package, see base64-js.
Common mistakes
First, follow advice from the handbook.
Formatting: Either use all tabs, or always use 4 spaces.
function sum(nums: number[]): number : Use ReadonlyArray if a function does not write to its parameters.
interface Foo { new(): Foo; } : This defines a type of objects that are new-able. You probably want declare
class Foo { constructor(); } .
const Class: { new(): IClass; } : Prefer to use a class declaration class Class { constructor(); } instead
of a new-able constant.
getMeAT<T>(): T : If a type parameter does not appear in the types of any parameters, you don't really have a
generic function, you just have a disguised type assertion. Prefer to use a real type assertion, e.g. getMeAT() as
number . Example where a type parameter is acceptable: function id<T>(value: T): T; . Example where it is not
acceptable: function parseJson<T>(json: string): T; . Exception: new Map<string, number>() is OK.
Using the types Function and Object is almost never a good idea. In 99% of cases it's possible to specify a more
specific type. Examples are (x: number) => number for functions and { x: number, y: number } for objects. If
there is no certainty at all about the type, any is the right choice, not Object . If the only known fact about the type
is that it's some object, use the type object , not Object or { [key: string]: any } .
var foo: string | any : When any is used in a union type, the resulting type is still any . So while the string
portion of this type annotation may look useful, it in fact offers no additional typechecking over simply using any .
Depending on the intention, acceptable alternatives could be any , string , or string | object .
Removing a package
When a package bundles its own types, types should be removed from DefinitelyTyped to avoid confusion.
You can remove it by running npm run not-needed -- typingsPackageName asOfVersion sourceRepoURL
[libraryName] .
Lint
All new packages must be linted. To lint a package, add a tslint.json to that package containing
{
"extends": "dtslint/dt.json"
}
This should be the only content in a finished project's tslint.json file. If a tslint.json turns rules off, this is
because that hasn't been fixed yet. For example:
{
"extends": "dtslint/dt.json",
"rules": {
// This package uses the Function type, and it will take effort to fix.
"ban-types": false
}
}
(To indicate that a lint rule truly does not apply, use // tslint:disable rule-name or better, //tslint:disable-
next-line rule-name .)
To assert that an expression is of a given type, use $ExpectType . To assert that an expression causes a compile error,
use $ExpectError .
// $ExpectType void
f(1);
// $ExpectError
f("one");
FAQ
What exactly is the relationship between this repository and the @types packages on NPM?
The master branch is automatically published to the @types scope on NPM thanks to types-publisher.
I'm writing a definition that depends on another definition. Should I use <reference types="" /> or an
import?
If the module you're referencing is an external module (uses export ), use an import. If the module you're referencing is
an ambient module (uses declare module , or just declares globals), use <reference types="" /> .
I notice some packages having a package.json here.
Usually you won't need this. When publishing a package we will normally automatically create a package.json for it. A
package.json may be included for the sake of specifying dependencies. Here's an example. We do not allow other
fields, such as "description" , to be defined manually. Also, if you need to reference an older version of typings, you
must do that by adding "dependencies": { "@types/foo": "x.y.z" } to the package.json.
Some packages have no tslint.json , and some tsconfig.json are missing "noImplicitAny": true ,
"noImplicitThis": true , or "strictNullChecks": true .
Then they are wrong. You can help by submitting a pull request to fix them.
Should I add an empty namespace to a package that doesn't export a module to use ES6 style imports?
Some packages, like chai-http, export a function.
Importing this module with an ES6 style import in the form import * as foo from "foo"; leads to the error:
error TS2497: Module 'foo' resolves to a non-module entity and cannot be imported using this construct
This error can be suppressed by merging the function declaration with an empty namespace of the same name, but this
practice is discouraged. This is a commonly cited Stack Overflow answer regarding this matter.
It is more appropriate to import the module using the import foo = require("foo"); syntax. Nevertheless, if you
want to use a default import like import foo from "foo"; you have two options:
you can use the --allowSyntheticDefaultImports compiler option if your module runtime supports an interop
scheme for non-ECMAScript modules, i.e. if default imports work in your environment (e.g. Webpack, SystemJS,
esm).
you can use the --esModuleInterop compiler option if you want TypeScript to take care of non-ECMAScript
interop (since Typescript 2.7).
A package uses export = , but I prefer to use default imports. Can I change export = to export
default ?
Like in the previous question, refer to using either the --allowSyntheticDefaultImports or --esModuleInterop
compiler options.
Do not change the type definition if it is accurate. For an NPM package, export = is accurate if node -p
'require("foo")' works to import a module, and export default is accurate if node -p
'require("foo").default' works to import a module.
{
"private": true,
"types": "index",
"typesVersions": {
">=3.1.0-0": { "*": ["ts3.1/*"] }
}
}
2. Create the sub-directory mentioned in the typesVersions field inside your types directory ( ts3.1/ in this
example) and add the types and tests specific for the new TypeScript version. You don't need the typical definition
header in any of the files from the ts3.1/ directory.
3. Set the baseUrl and typeRoots options in ts3.1/tsconfig.json to the correct paths, they should look
something like this:
{
"compilerOptions": {
"baseUrl": "../../",
"typeRoots": ["../../"]
}
}
Because 10.12 is at the end the first line, the npm version of the @types/node package will also be 10.12.x . Note
that the first-line comment in the index.d.ts file should only contain the major.minor version (e.g. 10.12 ) and
should not contain a patch version (e.g. 10.12.4 ). This is because only the major and minor release numbers are
aligned between library packages and type declaration packages. The patch release number of the type declaration
package (e.g. .0 in 10.12.0 ) is initialized to zero by DefinitelyTyped and is incremented each time a new
@types/node package is published to NPM for the same major/minor version of the corresponding library.
Sometimes type declaration package versions and library package versions can get out of sync. Below are a few
common reasons why, in order of how much they inconvenience users of a library. Only the last case is typically
problematic.
As noted above, the patch version of the type declaration package is unrelated to the library patch version. This
allows DefinitelyTyped to safely update type declarations for the same major/minor version of a library.
If updating a package for new functionality, don't forget to update the version number to line up with that version
of the library. If users make sure versions correspond between JavaScript packages and their respective @types
packages, then npm update should typically just work.
It's common for type declaration package updates to lag behind library updates because it's often library users, not
maintainers, who update DefinitelyTyped when new library features are released. So there may be a lag of days,
weeks, or even months before a helpful community member sends a PR to update the type declaration package for
a new library release. If you're impacted by this, you can be the change you want to see in the world and you can be
that helpful community member!
If you're updating type declarations for a library, always set the major.minor version in the first line of index.d.ts
to match the library version that you're documenting!
If a library is updated to a new major version with breaking changes, how should I update its type
declaration package?
Semantic versioning requires that versions with breaking changes must increment the major version number.
For example, a library that removes a publicly exported function after its 3.5.8 release must bump its version to
4.0.0 in its next release.
Furthermore, when the library's 4.0.0 release is out, its DefinitelyTyped type declaration package should also be
updated to 4.0.0 , including any breaking changes to the library's API.
Many libraries have a large installed base of developers (including maintainers of other packages using that library as a
dependency) who won't move right away to a new version that has breaking changes, because it might be months until
a maintainer has time to rewrite code to adapt to the new version. In the meantime, users of old library versions still
may want to update type declarations for older versions.
If you intend to continue updating the older version of a library's type declarations, you may create a new subfolder (e.g.
/v2/ ) named for the current (soon to be "old") version, and copy existing files from the current version to it.
Because the root folder should always contain the type declarations for the latest ("new") version, you'll need to make a
few changes to the files in your old-version subdirectory to ensure that relative path references point to the
subdirectory, not the root.
1. Update the relative paths in tsconfig.json as well as tslint.json .
2. Add path mapping rules to ensure that tests are running against the intended version.
For example, the history library introduced breaking changes between version 2.x and 3.x .
Because many users still consumed the older 2.x version, a maintainer who wanted to update the type declarations for
this library to 3.x added a v2 folder inside the history repository that contains type declarations for the older version.
At the time of writing, the history v2 tsconfig.json looks roughly like:
{
"compilerOptions": {
"baseUrl": "../../",
"typeRoots": ["../../"],
"paths": {
"history": [ "history/v2" ]
},
},
"files": [
"index.d.ts",
"history-tests.ts"
]
}
If there are other packages in DefinitelyTyped that are incompatible with the new version, you will need to add path
mappings to the old version. You will also need to do this recursively for packages depending on packages depending
on the old version.
For example, react-router depends on history@2 , so react-router tsconfig.json has a path mapping to
"history": [ "history/v2" ] . Transitively, react-router-bootstrap (which depends on react-router ) also
needed to add the same path mapping ( "history": [ "history/v2" ] ) in its tsconfig.json until its react-router
dependency was updated to the latest version.
Also, /// <reference types=".." /> will not work with path mapping, so dependencies must use import .
How do I write definitions for packages that can be used globally and as a module?
The TypeScript handbook contains excellent general information about writing definitions, and also this example
definition file which shows how to create a definition using ES6-style module syntax, while also specifying objects made
available to the global scope. This technique is demonstrated practically in the definition for big.js, which is a library that
can be loaded globally via script tag on a web page, or imported via require or ES6-style imports.
To test how your definition can be used both when referenced globally or as an imported module, create a test folder,
and place two test files in there. Name one YourLibraryName-global.test.ts and the other YourLibraryName-
module.test.ts . The global test file should exercise the definition according to how it would be used in a script loaded
on a web page where the library is available on the global scope - in this scenario you should not specify an import
statement. The module test file should exercise the definition according to how it would be used when imported
(including the import statement(s)). If you specify a files property in your tsconfig.json file, be sure to include
both test files. A practical example of this is also available on the big.js definition.
Please note that it is not required to fully exercise the definition in each test file - it is sufficient to test only the globally-
accessible elements on the global test file and fully exercise the definition in the module test file, or vice versa.
{
"paths":{
"@foo/bar": ["foo__bar"]
}
}
License
This project is licensed under the MIT license.
Copyrights on the definition files are respective of each contributor listed at the beginning of each definition file.
Releases
No releases published
Languages
TypeScript 100.0%