diff --git a/.vscode/extensions.json b/.vscode/extensions.json index 57a03d0b73f7..d5c1278d48e2 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -4,4 +4,4 @@ "streetsidesoftware.code-spell-checker-portuguese-brazilian", "streetsidesoftware.code-spell-checker-spanish" ] -} \ No newline at end of file +} diff --git a/docs/Converting Twoslash Code Samples.md b/docs/Converting Twoslash Code Samples.md index a559b4553925..06ac98e6e6b2 100644 --- a/docs/Converting Twoslash Code Samples.md +++ b/docs/Converting Twoslash Code Samples.md @@ -1,5 +1,7 @@ ### A Guide to Converting to Twoslash +To run the site with Twoslash enabled you need to use `yarn start-twoslash`. + Code samples on the TypeScript Website should run through [Twoslash](https://github.com/microsoft/TypeScript-Website/tree/v2/packages/ts-twoslasher#typescript-twoslash) which lets the compiler do more of the work. Without twoslash a code sample looks like: diff --git a/packages/documentation/copy/en/Basic Types.md b/packages/documentation/copy/en/Basic Types.md index 7486dab2d494..dae60c08af54 100644 --- a/packages/documentation/copy/en/Basic Types.md +++ b/packages/documentation/copy/en/Basic Types.md @@ -10,7 +10,7 @@ oneline: "Step one in learning TypeScript: The basics types." For programs to be useful, we need to be able to work with some of the simplest units of data: numbers, strings, structures, boolean values, and the like. In TypeScript, we support much the same types as you would expect in JavaScript, with a convenient enumeration type thrown in to help things along. -# Boolean +## Boolean The most basic datatype is the simple true/false value, which JavaScript and TypeScript call a `boolean` value. @@ -18,7 +18,7 @@ The most basic datatype is the simple true/false value, which JavaScript and Typ let isDone: boolean = false; ``` -# Number +## Number As in JavaScript, all numbers in TypeScript are either floating point values or BigIntegers. These floating point numbers get the type `number`, while BigIntegers get the type `bigint`. @@ -33,7 +33,7 @@ let octal: number = 0o744; let big: bigint = 100n; ``` -# String +## String Another fundamental part of creating programs in JavaScript for webpages and servers alike is working with textual data. As in other languages, we use the type `string` to refer to these textual datatypes. @@ -70,7 +70,7 @@ let sentence: string = " years old next month."; ``` -# Array +## Array TypeScript, like JavaScript, allows you to work with arrays of values. Array types can be written in one of two ways. @@ -125,7 +125,7 @@ x[3] = "world"; console.log(x[5].toString()); ``` -# Enum +## Enum A helpful addition to the standard set of datatypes from JavaScript is the `enum`. As in languages like C#, an enum is a way of giving more friendly names to sets of numeric values. @@ -215,7 +215,7 @@ if (typeof maybe === "string") { } ``` -# Any +## Any In some situations, not all type information is available or it's declaration would take an inappropriate amount of effort. These may occur for values from code that has been written without TypeScript or a 3rd party library. @@ -256,7 +256,7 @@ let d = looselyTyped.a.b.c.d; After all, remember that all the convenience of `any` comes at the cost of losing type safety. Type safety is one of the main motivations for using TypeScript and you should try to avoid using `any` when not necessary. -# Void +## Void `void` is a little like the opposite of `any`: the absence of having any type at all. You may commonly see this as the return type of functions that do not return a value: @@ -298,7 +298,7 @@ Union types are an advanced topic that we'll cover in a later chapter. > As a note: we encourage the use of `--strictNullChecks` when possible, but for the purposes of this handbook, we will assume it is turned off. -# Never +## Never The `never` type represents the type of values that never occur. For instance, `never` is the return type for a function expression or an arrow function expression that always throws an exception or one that never returns. @@ -348,7 +348,7 @@ create(undefined); Generally, you won't need to use this. -# Type assertions +## Type assertions Sometimes you'll end up in a situation where you'll know more about a value than TypeScript does. Usually this will happen when you know the type of some entity could be more specific than its current type. @@ -384,3 +384,30 @@ Using one over the other is mostly a choice of preference; however, when using T You may have noticed that so far, we've been using the `let` keyword instead of JavaScript's `var` keyword which you might be more familiar with. The `let` keyword is actually a newer JavaScript construct that TypeScript makes available. We'll discuss the details later, but many common problems in JavaScript are alleviated by using `let`, so you should use it instead of `var` whenever possible. + + +## About `Number`, `String`, `Boolean`, `Symbol` and `Object` + +It can be tempting to think that the types `Number`, `String`, `Boolean`, `Symbol`, or `Object` are the same as the lowercase versions. +These types do not refer to the language primitives, and almost never should be used as a type. + +```ts twoslash +// @errors: 2339 +function reverse(s: String): String { + return s.split("").reverse().join("") +} + +reverse("hello world") +``` + +Instead, use the types `number`, `string`, `boolean`, and `symbol`. + +```ts twoslash +function reverse(s: string): string { + return s.split("").reverse().join("") +} + +reverse("hello world") +``` + +Instead of `Object`, use the non-primitive `object` type diff --git a/packages/documentation/copy/en/declaration files/By Example.md b/packages/documentation/copy/en/declaration files/By Example.md index a7ff64e06504..6717d697f834 100644 --- a/packages/documentation/copy/en/declaration files/By Example.md +++ b/packages/documentation/copy/en/declaration files/By Example.md @@ -1,63 +1,16 @@ --- -title: By Example +title: Declaration Reference layout: docs permalink: /docs/handbook/declaration-files/by-example.html oneline: "How to create a d.ts file for a module" --- -# Introduction - The purpose of this guide is to teach you how to write a high-quality definition file. This guide is structured by showing documentation for some API, along with sample usage of that API, and explaining how to write the corresponding declaration. These examples are ordered in approximately increasing order of complexity. -# The Examples - -## Global Variables - -_Documentation_ - -> The global variable `foo` contains the number of widgets present. - -_Code_ - -```ts -console.log("Half the number of widgets is " + foo / 2); -``` - -_Declaration_ - -Use `declare var` to declare variables. -If the variable is read-only, you can use `declare const`. -You can also use `declare let` if the variable is block-scoped. - -```ts -/** The number of widgets present */ -declare var foo: number; -``` - -## Global Functions - -_Documentation_ - -> You can call the function `greet` with a string to show a greeting to the user. - -_Code_ - -```ts -greet("hello, world"); -``` - -_Declaration_ - -Use `declare function` to declare functions. - -```ts -declare function greet(greeting: string): void; -``` - ## Objects with Properties _Documentation_ @@ -253,23 +206,46 @@ declare class Greeter { } ``` - diff --git a/packages/documentation/copy/en/declaration files/Deep Dive.md b/packages/documentation/copy/en/declaration files/Deep Dive.md index f7373a37342c..89950e967a42 100644 --- a/packages/documentation/copy/en/declaration files/Deep Dive.md +++ b/packages/documentation/copy/en/declaration files/Deep Dive.md @@ -5,19 +5,19 @@ permalink: /docs/handbook/declaration-files/deep-dive.html oneline: "How do d.ts files work, a deep dive" --- -# Definition File Theory: A Deep Dive +## Declaration File Theory: A Deep Dive Structuring modules to give the exact API shape you want can be tricky. For example, we might want a module that can be invoked with or without `new` to produce different types, has a variety of named types exposed in a hierarchy, and has some properties on the module object as well. -By reading this guide, you'll have the tools to write complex definition files that expose a friendly API surface. +By reading this guide, you'll have the tools to write complex declaration files that expose a friendly API surface. This guide focuses on module (or UMD) libraries because the options here are more varied. ## Key Concepts -You can fully understand how to make any shape of definition +You can fully understand how to make any shape of declaration by understanding some key concepts of how TypeScript works. ### Types @@ -229,8 +229,4 @@ The second block creates the following name meanings: - A value `C` that is a property of the `X.Z` value - A type `X` -## Using with `export =` or `import` - -An important rule is that `export` and `import` declarations export or import _all meanings_ of their targets. - diff --git a/packages/documentation/copy/en/declaration files/Do's and Don'ts.md b/packages/documentation/copy/en/declaration files/Do's and Don'ts.md index d92d83230a74..1c4fcb2781f5 100644 --- a/packages/documentation/copy/en/declaration files/Do's and Don'ts.md +++ b/packages/documentation/copy/en/declaration files/Do's and Don'ts.md @@ -35,7 +35,7 @@ See more details in [TypeScript FAQ page](https://github.com/Microsoft/TypeScrip _Don't_ use `any` as a type unless you are in the process of migrating a JavaScript project to TypeScript. The compiler _effectively_ treats `any` as "please turn off type checking for this thing". It is similar to putting an `@ts-ignore` comment around every usage of the variable. This can be very helpful when you are first migrating a JavaScript project to TypeScript as you can set the type for stuff you haven't migrated yet as `any`, but in a full TypeScript project you are disabling type checking for any parts of your program that use it. -In cases where you don't know what type you want to accept, or when you want to accept anything because you will be blindly passing it through without interacting with it, you can use [`unknown`](/play/index.html?e=136#example/unknown-and-never). +In cases where you don't know what type you want to accept, or when you want to accept anything because you will be blindly passing it through without interacting with it, you can use [`unknown`](/play/#example/unknown-and-never). diff --git a/packages/documentation/copy/en/declaration files/Introduction.md b/packages/documentation/copy/en/declaration files/Introduction.md index 54c88abd40ba..65d07ea733c8 100644 --- a/packages/documentation/copy/en/declaration files/Introduction.md +++ b/packages/documentation/copy/en/declaration files/Introduction.md @@ -2,30 +2,33 @@ title: Introduction layout: docs permalink: /docs/handbook/declaration-files/introduction.html -oneline: "How to write a high-quality TypeScript Ddeclaration (d.ts) file" +oneline: "How to write a high-quality TypeScript Declaration (d.ts) file" --- -This guide is designed to teach you how to write a high-quality TypeScript Declaration File. +This guide is designed to teach you how to write a high-quality TypeScript Declaration File. We need to assume basic familiarity with the TypeScript language in order to get started. -We assume basic familiarity with the TypeScript language. If you haven't already, you should read the [TypeScript Handbook](https://www.typescriptlang.org/docs/handbook/basic-types.html) -to familiarize yourself with basic concepts, especially types and namespaces. +to familiarize yourself with basic concepts, especially types and modules. -# Sections +The most common case for learning how .d.ts files work is that you're typing an npm package with no types. +In that case, you can jump straight to [Modules .d.ts](/docs/handbook/declaration-files/templates/module-d-ts.html). -The guide is broken down into the following sections. +The Declaration Files guide is broken down into the following sections. + +## Declaration Reference + +We are often faced with writing a declaration file when we only have examples of the underlying library to guide us. +The [Declaration Reference](/docs/handbook/declaration-files/by-example.html) section shows many common API patterns and how to write declarations for each of them. +This guide is aimed at the TypeScript novice who may not yet be familiar with every language construct in TypeScript. ## Library Structures The [Library Structures](/docs/handbook/declaration-files/library-structures.html) guide helps you understand common library formats and how to write a proper declaration file for each format. If you're editing an existing file, you probably don't need to read this section. -Authors of new declaration files are strongly encouraged to read this section to properly understand how the format of the library influences the writing of the declaration file. +Authors of new declaration files are strongly encouraged to read this section to properly understand how the format of the library influences the writing of the declaration file. -## By Example - -We are often faced with writing a declaration file when we only have examples of the underlying library to guide us. -The [By Example](/docs/handbook/declaration-files/by-example.html) section shows many common API patterns and how to write declarations for each of them. -This guide is aimed at the TypeScript novice who may not yet be familiar with every language construct in TypeScript. +In the Template section you'll find a number of declaration files that serve as a useful starting point +when writing a new file. If you already know what your structure is, see the d.ts Template section in the sidebar. ## "Do"s and "Don't"s @@ -41,12 +44,6 @@ For seasoned authors interested in the underlying mechanics of how declaration f the [Deep Dive](/docs/handbook/declaration-files/deep-dive.html) section explains many advanced concepts in declaration writing, and shows how to leverage these concepts to create cleaner and more intuitive declaration files. -## Templates - -In [Templates](/docs/handbook/declaration-files/templates.html) you'll find a number of declaration files that serve as a useful starting point -when writing a new file. -Refer to the documentation in [Library Structures](/docs/handbook/declaration-files/library-structures.html) to figure out which template file to use. - ## Publish to npm The [Publishing](/docs/handbook/declaration-files/publishing.html) section explains how to publish your declaration files to an npm package, and shows how to manage your dependent packages. diff --git a/packages/documentation/copy/en/declaration files/Library Structures.md b/packages/documentation/copy/en/declaration files/Library Structures.md index 6cefbe9bdb22..85b95e45ba69 100644 --- a/packages/documentation/copy/en/declaration files/Library Structures.md +++ b/packages/documentation/copy/en/declaration files/Library Structures.md @@ -5,8 +5,6 @@ permalink: /docs/handbook/declaration-files/library-structures.html oneline: How to structure your d.ts files --- -# Overview - Broadly speaking, the way you _structure_ your declaration file depends on how the library is consumed. There are many ways of offering a library for consumption in JavaScript, and you'll need to write your declaration file to match it. This guide covers how to identify common library patterns, and how to write declaration files which correspond to that pattern. @@ -24,6 +22,97 @@ We'll give hints on how to identify structure both based on its _usage_ and its Depending on the library's documentation and organization, one might be easier than the other. We recommend using whichever is more comfortable to you. +## What should you look for? + +Question to ask yourself while looking at a library you are trying to type. + +1. How do you obtain the library? + + For example, can you _only_ get it through npm or only from a CDN? + +2. How would you import it? + + Does it add a global object? Does it use `require` or `import`/`export` statements? + +## Smaller samples for different types of libraries + +## Modular Libraries + +Almost every modern Node.js library falls into the module family. +These type of libraries only work in a JS environment with a module loader. +For example, `express` only works in Node.js and must be loaded using the CommonJS `require` function. + +ECMAScript 2015 (also known as ES2015, ECMAScript 6, and ES6), CommonJS, and RequireJS have similar notions of _importing_ a _module_. +In JavaScript CommonJS (Node.js), for example, you would write + +```js +var fs = require("fs"); +``` + +In TypeScript or ES6, the `import` keyword serves the same purpose: + +```ts +import * as fs from "fs"; +``` + +You'll typically see modular libraries include one of these lines in their documentation: + +```js +var someLib = require("someLib"); +``` + +or + +```js +define(..., ['someLib'], function(someLib) { + +}); +``` + +As with global modules, you might see these examples in the documentation of [a UMD](#module) module, so be sure to check the code or documentation. + +### Identifying a Module Library from Code + +Modular libraries will typically have at least some of the following: + +- Unconditional calls to `require` or `define` +- Declarations like `import * as a from 'b';` or `export c;` +- Assignments to `exports` or `module.exports` + +They will rarely have: + +- Assignments to properties of `window` or `global` + +### Templates For Modules + +There are four templates available for modules, +[`module.d.ts`](/docs/handbook/declaration-files/templates/module-d-ts.html), [`module-class.d.ts`](/docs/handbook/declaration-files/templates/module-class-d-ts.html), [`module-function.d.ts`](/docs/handbook/declaration-files/templates/module-function-d-ts.html) and [`module-plugins.d.ts`](/docs/handbook/declaration-files/templates/module-plugins-d-ts.html). + +You should first read [`module.d.ts`](/docs/handbook/declaration-files/templates/module-d-ts.html) for an overview on the way they all work. + +Then use the template [`module-function.d.ts`](/docs/handbook/declaration-files/templates/module-function-d-ts.html) if your module can be _called_ like a function: + +```js +const x = require("foo"); +// Note: calling 'x' as a function +const y = x(42); +``` + +Use the template [`module-class.d.ts`](/docs/handbook/declaration-files/templates/module-class-d-ts.html) if your module can be _constructed_ using `new`: + +```js +const x = require("bar"); +// Note: using 'new' operator on the imported variable +const y = new x("hello"); +``` + +If you have a module which when imported, makes changes to other modules use template [`module-plugin.d.ts`](/docs/handbook/declaration-files/templates/module-plugin-d-ts.html): + +```js +const jest = require("jest"); +require("jest-matchers-files"); +``` + ## Global Libraries A _global_ library is one that can be accessed from the global scope (i.e. without using any form of `import`). @@ -60,7 +149,18 @@ function createGreeting(s) { or like this: ```js -window.createGreeting = function(s) { +// Web +window.createGreeting = function (s) { + return "Hello, " + s; +}; + +// Node +global.createGreeting = function (s) { + return "Hello, " + s; +}; + +// Potentially any runtime +globalThis.createGreeting = function (s) { return "Hello, " + s; }; ``` @@ -88,56 +188,6 @@ However, libraries that are small and require the DOM (or have _no_ dependencies The template file [`global.d.ts`](/docs/handbook/declaration-files/templates/global-plugin-d-ts.html) defines an example library `myLib`. Be sure to read the ["Preventing Name Conflicts" footnote](#preventing-name-conflicts). -## Modular Libraries - -Some libraries only work in a module loader environment. -For example, `express` only works in Node.js and must be loaded using the CommonJS `require` function. - -ECMAScript 2015 (also known as ES2015, ECMAScript 6, and ES6), CommonJS, and RequireJS have similar notions of _importing_ a _module_. -In JavaScript CommonJS (Node.js), for example, you would write - -```js -var fs = require("fs"); -``` - -In TypeScript or ES6, the `import` keyword serves the same purpose: - -```ts -import fs = require("fs"); -``` - -You'll typically see modular libraries include one of these lines in their documentation: - -```js -var someLib = require("someLib"); -``` - -or - -```js -define(..., ['someLib'], function(someLib) { - -}); -``` - -As with global modules, you might see these examples in the documentation of a UMD module, so be sure to check the code or documentation. - -### Identifying a Module Library from Code - -Modular libraries will typically have at least some of the following: - -- Unconditional calls to `require` or `define` -- Declarations like `import * as a from 'b';` or `export c;` -- Assignments to `exports` or `module.exports` - -They will rarely have: - -- Assignments to properties of `window` or `global` - -### Examples of Modular Libraries - -Many popular Node.js libraries are in the module family, such as [`express`](http://expressjs.com/), [`gulp`](http://gulpjs.com/), and [`request`](https://github.com/request/request). - ## _UMD_ A _UMD_ module is one that can _either_ be used as module (through an import), or as a global (when run in an environment without a module loader). @@ -184,102 +234,8 @@ Examples include [jQuery](https://jquery.com/), [Moment.js](http://momentjs.com/ ### Template -There are three templates available for modules, -[`module.d.ts`](/docs/handbook/declaration-files/templates/module-d-ts.html), [`module-class.d.ts`](/docs/handbook/declaration-files/templates/module-class-d-ts.html) and [`module-function.d.ts`](/docs/handbook/declaration-files/templates/module-function-d-ts.html). - -Use [`module-function.d.ts`](/docs/handbook/declaration-files/templates/module-function-d-ts.html) if your module can be _called_ like a function: - -```js -var x = require("foo"); -// Note: calling 'x' as a function -var y = x(42); -``` - -Be sure to read the [footnote "The Impact of ES6 on Module Call Signatures"](#the-impact-of-es6-on-module-plugins) - -Use [`module-class.d.ts`](/docs/handbook/declaration-files/templates/module-class-d-ts.html) if your module can be _constructed_ using `new`: - -```js -var x = require("bar"); -// Note: using 'new' operator on the imported variable -var y = new x("hello"); -``` - -The same [footnote](#the-impact-of-es6-on-module-plugins) applies to these modules. - -If your module is not callable or constructable, use the [`module.d.ts`](/docs/handbook/declaration-files/templates/module-d-ts.html) file. - -## _Module Plugin_ or _UMD Plugin_ - -A _module plugin_ changes the shape of another module (either UMD or module). -For example, in Moment.js, `moment-range` adds a new `range` method to the `moment` object. - -For the purposes of writing a declaration file, you'll write the same code whether the module being changed is a plain module or UMD module. - -### Template - Use the [`module-plugin.d.ts`](/docs/handbook/declaration-files/templates/module-plugin-d-ts.html) template. -## _Global Plugin_ - -A _global plugin_ is global code that changes the shape of some global. -As with _global-modifying modules_, these raise the possibility of runtime conflict. - -For example, some libraries add new functions to `Array.prototype` or `String.prototype`. - -### Identifying global plugins - -Global plugins are generally easy to identify from their documentation. - -You'll see examples that look like this: - -```js -var x = "hello, world"; -// Creates new methods on built-in types -console.log(x.startsWithHello()); - -var y = [1, 2, 3]; -// Creates new methods on built-in types -console.log(y.reverseAndSort()); -``` - -### Template - -Use the [`global-plugin.d.ts`](/docs/handbook/declaration-files/templates/global-plugin-d-ts.html) template. - -## _Global-modifying Modules_ - -A _global-modifying module_ alters existing values in the global scope when they are imported. -For example, there might exist a library which adds new members to `String.prototype` when imported. -This pattern is somewhat dangerous due to the possibility of runtime conflicts, -but we can still write a declaration file for it. - -### Identifying global-modifying modules - -Global-modifying modules are generally easy to identify from their documentation. -In general, they're similar to global plugins, but need a `require` call to activate their effects. - -You might see documentation like this: - -```js -// 'require' call that doesn't use its return value -var unused = require("magic-string-time"); -/* or */ -require("magic-string-time"); - -var x = "hello, world"; -// Creates new methods on built-in types -console.log(x.startsWithHello()); - -var y = [1, 2, 3]; -// Creates new methods on built-in types -console.log(y.reverseAndSort()); -``` - -### Template - -Use the [`global-modifying-module.d.ts`](./templates/global-modifying-module.d.ts.md) template. - # Consuming Dependencies There are several kinds of dependencies your library might have. @@ -352,12 +308,6 @@ interface CatsKittySettings {} This guidance also ensures that the library can be transitioned to UMD without breaking declaration file users. -## The Impact of ES6 on Module Plugins - -Some plugins add or modify top-level exports on existing modules. -While this is legal in CommonJS and other loaders, ES6 modules are considered immutable and this pattern will not be possible. -Because TypeScript is loader-agnostic, there is no compile-time enforcement of this policy, but developers intending to transition to an ES6 module loader should be aware of this. - ## The Impact of ES6 on Module Call Signatures Many popular libraries, such as Express, expose themselves as a callable function when imported. @@ -368,42 +318,9 @@ import exp = require("express"); var app = exp(); ``` -In ES6 module loaders, the top-level object (here imported as `exp`) can only have properties; -the top-level module object is _never_ callable. -The most common solution here is to define a `default` export for a callable/constructable object; -some module loader shims will automatically detect this situation and replace the top-level object with the `default` export. - -## Library file layout - -The layout of your declaration files should mirror the layout of the library. - -A library can consist of multiple modules, such as - -``` -myLib - +---- index.js - +---- foo.js - +---- bar - +---- index.js - +---- baz.js -``` - -These could be imported as +In ES6-compl module loaders, the top-level object (here imported as `exp`) can only have properties; +the top-level module object can _never_ be callable. -```js -var a = require("myLib"); -var b = require("myLib/foo"); -var c = require("myLib/bar"); -var d = require("myLib/bar/baz"); -``` - -Your declaration files should thus be - -``` -@types/myLib - +---- index.d.ts - +---- foo.d.ts - +---- bar - +---- index.d.ts - +---- baz.d.ts -``` +The most common solution here is to define a `default` export for a callable/constructable object; +module loaders commonly detect this situation automatically and replace the top-level object with the `default` export. +Typescript can handle this for you, if you have [`"esModuleInterop": true`](/tsconfig/#esModuleInterop) in tsconfig.json. diff --git a/packages/documentation/copy/en/declaration files/Publishing.md b/packages/documentation/copy/en/declaration files/Publishing.md index dcfa6baed602..65b9f36dc45d 100644 --- a/packages/documentation/copy/en/declaration files/Publishing.md +++ b/packages/documentation/copy/en/declaration files/Publishing.md @@ -8,16 +8,14 @@ oneline: How to get your d.ts files to users Now that you have authored a declaration file following the steps of this guide, it is time to publish it to npm. There are two main ways you can publish your declaration files to npm: -1. bundling with your npm package, or +1. bundling with your npm package 2. publishing to the [@types organization](https://www.npmjs.com/~types) on npm. -If your package is written in TypeScript then the first approach is favored. -Use the `--declaration` flag to generate declaration files. -This way, your declarations and JavaScript will always be in sync. +If your types are generated by your source code, publish the types with your source code. Both TypeScript and JavaScript projects can generate types via [`--declaration`](/tsconfig#declaration). -If your package is not written in TypeScript then the second is the preferred approach. +Otherwise, we recommend submitting the types to DefinitelyTyped, which will publish them to the `@types` organization on npm. -# Including declarations in your npm package +## Including declarations in your npm package If your package has a main `.js` file, you will need to indicate the main declaration file in your `package.json` file as well. Set the `types` property to point to your bundled declaration file. diff --git a/packages/documentation/copy/en/declaration files/templates/global-modifying-module.d.ts.md b/packages/documentation/copy/en/declaration files/templates/global-modifying-module.d.ts.md index 7411310c7d31..7b2d004e3798 100644 --- a/packages/documentation/copy/en/declaration files/templates/global-modifying-module.d.ts.md +++ b/packages/documentation/copy/en/declaration files/templates/global-modifying-module.d.ts.md @@ -1,9 +1,40 @@ --- -title: global-modifying-module.d.ts +title: "Global: Modifying Module" layout: docs permalink: /docs/handbook/declaration-files/templates/global-modifying-module-d-ts.html --- +## _Global-modifying Modules_ + +A _global-modifying module_ alters existing values in the global scope when they are imported. +For example, there might exist a library which adds new members to `String.prototype` when imported. +This pattern is somewhat dangerous due to the possibility of runtime conflicts, +but we can still write a declaration file for it. + +## Identifying global-modifying modules + +Global-modifying modules are generally easy to identify from their documentation. +In general, they're similar to global plugins, but need a `require` call to activate their effects. + +You might see documentation like this: + +```js +// 'require' call that doesn't use its return value +var unused = require("magic-string-time"); +/* or */ +require("magic-string-time"); + +var x = "hello, world"; +// Creates new methods on built-in types +console.log(x.startsWithHello()); + +var y = [1, 2, 3]; +// Creates new methods on built-in types +console.log(y.reverseAndSort()); +``` + +Here is an example + ```ts // Type definitions for [~THE LIBRARY NAME~] [~OPTIONAL VERSION NUMBER~] // Project: [~THE PROJECT NAME~] diff --git a/packages/documentation/copy/en/declaration files/templates/global-plugin.d.ts.md b/packages/documentation/copy/en/declaration files/templates/global-plugin.d.ts.md index 218daec250aa..85d48cf59f1a 100644 --- a/packages/documentation/copy/en/declaration files/templates/global-plugin.d.ts.md +++ b/packages/documentation/copy/en/declaration files/templates/global-plugin.d.ts.md @@ -1,9 +1,279 @@ --- -title: global-plugin.d.ts +title: "Global: Plugin" layout: docs permalink: /docs/handbook/declaration-files/templates/global-plugin-d-ts.html --- +## _UMD_ + +A _UMD_ module is one that can _either_ be used as module (through an import), or as a global (when run in an environment without a module loader). +Many popular libraries, such as [Moment.js](http://momentjs.com/), are written this way. +For example, in Node.js or using RequireJS, you would write: + +```ts +import moment = require("moment"); +console.log(moment.format()); +``` + +whereas in a vanilla browser environment you would write: + +```js +console.log(moment.format()); +``` + +### Identifying a UMD library + +[UMD modules](https://github.com/umdjs/umd) check for the existence of a module loader environment. +This is an easy-to-spot pattern that looks something like this: + +```js +(function (root, factory) { + if (typeof define === "function" && define.amd) { + define(["libName"], factory); + } else if (typeof module === "object" && module.exports) { + module.exports = factory(require("libName")); + } else { + root.returnExports = factory(root.libName); + } +}(this, function (b) { +``` + +If you see tests for `typeof define`, `typeof window`, or `typeof module` in the code of a library, especially at the top of the file, it's almost always a UMD library. + +Documentation for UMD libraries will also often demonstrate a "Using in Node.js" example showing `require`, +and a "Using in the browser" example showing using a ` +``` + +Today, most popular globally-accessible libraries are actually written as UMD libraries (see below). +UMD library documentation is hard to distinguish from global library documentation. +Before writing a global declaration file, make sure the library isn't actually UMD. + +## Identifying a Global Library from Code + +Global library code is usually extremely simple. +A global "Hello, world" library might look like this: + +```js +function createGreeting(s) { + return "Hello, " + s; +} +``` + +or like this: + +```js +window.createGreeting = function (s) { + return "Hello, " + s; +}; +``` + +When looking at the code of a global library, you'll usually see: + +- Top-level `var` statements or `function` declarations +- One or more assignments to `window.someName` +- Assumptions that DOM primitives like `document` or `window` exist + +You _won't_ see: + +- Checks for, or usage of, module loaders like `require` or `define` +- CommonJS/Node.js-style imports of the form `var fs = require("fs");` +- Calls to `define(...)` +- Documentation describing how to `require` or import the library + +## Examples of Global Libraries + +Because it's usually easy to turn a global library into a UMD library, very few popular libraries are still written in the global style. +However, libraries that are small and require the DOM (or have _no_ dependencies) may still be global. + +## Global Library Template + +You can see an example DTS below: + ```ts // Type definitions for [~THE LIBRARY NAME~] [~OPTIONAL VERSION NUMBER~] // Project: [~THE PROJECT NAME~] diff --git a/packages/documentation/copy/en/declaration files/templates/module-class.d.ts.md b/packages/documentation/copy/en/declaration files/templates/module-class.d.ts.md index 137698fcb4af..05257c75e11a 100644 --- a/packages/documentation/copy/en/declaration files/templates/module-class.d.ts.md +++ b/packages/documentation/copy/en/declaration files/templates/module-class.d.ts.md @@ -1,9 +1,27 @@ --- -title: module-class.d.ts +title: "Module: Class" layout: docs permalink: /docs/handbook/declaration-files/templates/module-class-d-ts.html --- + + +For example, when you want to work with JavaScript code which looks like: + +```ts +const Greeter = require("super-greeter"); + +const greeter = new Greeter(); +greeter.greet(); +``` + +To handle both importing via UMD and modules: + ```ts // Type definitions for [~THE LIBRARY NAME~] [~OPTIONAL VERSION NUMBER~] // Project: [~THE PROJECT NAME~] @@ -41,9 +59,9 @@ export = MyClass; /*~ Write your module's methods and properties in this class */ declare class MyClass { - constructor(someParam?: string); + constructor(customGreeting?: string); - someProperty: string[]; + greet: void; myMethod(opts: MyClass.MyClassMethodOptions): number; } diff --git a/packages/documentation/copy/en/declaration files/templates/module-function.d.ts.md b/packages/documentation/copy/en/declaration files/templates/module-function.d.ts.md index 885bdfe2d9c8..fde9ddf6d24c 100644 --- a/packages/documentation/copy/en/declaration files/templates/module-function.d.ts.md +++ b/packages/documentation/copy/en/declaration files/templates/module-function.d.ts.md @@ -1,9 +1,20 @@ --- -title: module-function.d.ts +title: "Module: Function" layout: docs permalink: /docs/handbook/declaration-files/templates/module-function-d-ts.html --- +For example, when you want to work with JavaScript code which looks like: + +```ts +import greeter from "super-greeter"; + +greeter(2); +greeter("Hello world"); +``` + +To handle both importing via UMD and modules: + ```ts // Type definitions for [~THE LIBRARY NAME~] [~OPTIONAL VERSION NUMBER~] // Project: [~THE PROJECT NAME~] @@ -37,11 +48,11 @@ export as namespace myFuncLib; /*~ This declaration specifies that the function *~ is the exported object from the file */ -export = MyFunction; +export = Greeter; /*~ This example shows how to have multiple overloads for your function */ -declare function MyFunction(name: string): MyFunction.NamedReturnType; -declare function MyFunction(length: number): MyFunction.LengthReturnType; +declare function Greeter(name: string): Greeter.NamedReturnType; +declare function Greeter(length: number): Greeter.LengthReturnType; /*~ If you want to expose types from your module as well, you can *~ place them in this block. Often you will want to describe the @@ -53,7 +64,7 @@ declare function MyFunction(length: number): MyFunction.LengthReturnType; *~ --esModuleInterop is turned on: *~ import * as x from '[~THE MODULE~]'; // WRONG! DO NOT DO THIS! */ -declare namespace MyFunction { +declare namespace Greeter { export interface LengthReturnType { width: number; height: number; @@ -65,7 +76,7 @@ declare namespace MyFunction { /*~ If the module also has properties, declare them here. For example, *~ this declaration says that this code is legal: - *~ import f = require('myFuncLibrary'); + *~ import f = require('super-greeter'); *~ console.log(f.defaultName); */ export const defaultName: string; diff --git a/packages/documentation/copy/en/declaration files/templates/module-plugin.d.ts.md b/packages/documentation/copy/en/declaration files/templates/module-plugin.d.ts.md index de4fc903e489..cad292ffc107 100644 --- a/packages/documentation/copy/en/declaration files/templates/module-plugin.d.ts.md +++ b/packages/documentation/copy/en/declaration files/templates/module-plugin.d.ts.md @@ -1,9 +1,38 @@ --- -title: module-plugin.d.ts +title: "Module: Plugin" layout: docs permalink: /docs/handbook/declaration-files/templates/module-plugin-d-ts.html --- +For example, when you want to work with JavaScript code which extends another library. + +```ts +import { greeter } from "super-greeter"; + +// Normal Greeter API +greeter(2); +greeter("Hello world"); + +// Now we extend the object with a new function at runtime +import "hyper-super-greeter"; +greeter.hyperGreet(); +``` + +The definition for "super-greeter": + +```ts +/*~ This example shows how to have multiple overloads for your function */ +export interface GreeterFunction { + (name: string): void + (time: number): +} + +/*~ This example shows how to export a function specified by an interface */ +export const greeter: GreeterFunction; +``` + +We can extend the existing module like the following: + ```ts // Type definitions for [~THE LIBRARY NAME~] [~OPTIONAL VERSION NUMBER~] // Project: [~THE PROJECT NAME~] @@ -16,27 +45,23 @@ permalink: /docs/handbook/declaration-files/templates/module-plugin-d-ts.html */ /*~ On this line, import the module which this module adds to */ -import * as m from "someModule"; - -/*~ You can also import other modules if needed */ -import * as other from "anotherModule"; - -/*~ Here, declare the same module as the one you imported above */ -declare module "someModule" { - /*~ Inside, add new function, classes, or variables. You can use - *~ unexported types from the original module if needed. */ - export function theNewMethod(x: m.foo): other.bar; - - /*~ You can also add new properties to existing interfaces from - *~ the original module by writing interface augmentations */ - export interface SomeModuleOptions { - someModuleSetting?: string; - } +import { greeter } from "super-greeter"; - /*~ New types can also be declared and will appear as if they - *~ are in the original module */ - export interface MyModulePluginOptions { - size: number; +/*~ Here, declare the same module as the one you imported above + *~ then we expand the existing declaration of the greeter function + */ +export module "super-greeter" { + export interface GreeterFunction { + /** Greets even better! */ + hyperGreet(): void; } } ``` + +This uses [declaration merging](/docs/handbook/declaration-merging.html) + +## The Impact of ES6 on Module Plugins + +Some plugins add or modify top-level exports on existing modules. +While this is legal in CommonJS and other loaders, ES6 modules are considered immutable and this pattern will not be possible. +Because TypeScript is loader-agnostic, there is no compile-time enforcement of this policy, but developers intending to transition to an ES6 module loader should be aware of this. diff --git a/packages/documentation/copy/en/declaration files/templates/module.d.ts.md b/packages/documentation/copy/en/declaration files/templates/module.d.ts.md index 339a34064906..ab2c76e8885c 100644 --- a/packages/documentation/copy/en/declaration files/templates/module.d.ts.md +++ b/packages/documentation/copy/en/declaration files/templates/module.d.ts.md @@ -1,9 +1,232 @@ --- -title: module.d.ts +title: Modules .d.ts layout: docs permalink: /docs/handbook/declaration-files/templates/module-d-ts.html --- +# Comparing JavaScript to an example DTS + +## Common CommonJS Patterns + +A module using CommonJS patterns uses `module.exports` to describe the exported values. For example, here is a module which exports a function and a numerical constant: + +```js +const maxInterval = 12; + +function getArrayLength(arr) { + return arr.slice; +} + +module.exports = { + getArrayLength, + maxInterval, +}; +``` + +This can be described by the following `.d.ts`: + +```ts +export function getArrayLength(arr: any[]): number; +export const maxInterval: 12; +``` + +The TypeScript playground can show you the `.d.ts` equivalent for JavaScript code. You can [try it yourself here](/play?useJavaScript=true#code/GYVwdgxgLglg9mABAcwKZQIICcsEMCeAMqmMlABYAUuOAlIgN6IBQiiW6IWSNWAdABsSZcswC+zCAgDOURAFtcADwAq5GKUQBeRAEYATM2by4AExBC+qJQAc4WKNO2NWKdNjxFhFADSvFquqk4sxAA). + +The `.d.ts` syntax intentionally looks like [ES Modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) syntax. +ES Modules was ratified by TC39 in 2019, while it has been available via transpilers for a long time, however if you have a JavaScript codebase using ES Modules: + +```js +export function getArrayLength(arr) { + return arr.length; +} +``` + +This would have the following `.d.ts` equivalent: + +```ts +export function getArrayLength(arr: any[]): number; +``` + +### Default Exports + +In CommonJS you can export any value as the default export, for example here is a regular expression module: + +```js +module.exports = /hello( world)?/; +``` + +Which can be described by the following .d.ts: + +```ts +const helloWorld: RegExp; +export default helloWorld; +``` + +Or a number: + +```js +module.exports = 3.142; +``` + +```ts +const pi: number; +export default pi; +``` + +One style of exporting in CommonJS is to export a function. +Because a function is also an object, then extra fields can be added are included in the export. + +```js +function getArrayLength(arr) { + return arr.slice; +} +getArrayLength.maxInterval = 12; + +module.exports = getArrayLength; +``` + +Which can be described with: + +```ts +export default function getArrayLength(arr: any[]): number; +export const maxInterval: 12; +``` + +Note that using `export default` in your .d.ts files requires [`esModuleInterop: true`](/tsconfig#esModuleInterop) to work. +If you can't have `esModuleInterop: true` in your project, such as when you're submitting a PR to Definitely Typed, you'll have to use the `export=` syntax instead. This older syntax is harder to use but works everywhere. +Here's how the above example would have to be written using `export=`: + +```ts +declare function getArrayLength(arr: any[]): number; +declare namespace getArrayLength { + declare const maxInterval: 12; +} + +export = getArrayLength; +``` + +See [Module: Functions](module-function.d.ts.md) for details of how that works, and the [Modules reference](/docs/handbook/modules.html) page. + +## Handling Many Consuming Import + +There are many ways to import a module in modern consuming code: + +```ts +const fastify = require("fastify"); +const { fastify } = require("fastify"); +import fastify = require("fastify"); +import * as Fastify from "fastify"; +import { fastify, FastifyInstance } from "fastify"; +import fastify from "fastify"; +import fastify, { FastifyInstance } from "fastify"; +``` + +Covering all of these cases requires the JavaScript code to actually support all of these patterns. +To support many of these patterns, a CommonJS module would need to look something like: + +```js +class FastifyInstance {} + +function fastify() { + return new FastifyInstance(); +} + +fastify.FastifyInstance = FastifyInstance; + +// Allows for { fastify } +fastify.fastify = fastify; +// Allows for strict ES Module support +fastify.default = fastify; +// Sets the default export +module.exports = fastify; +``` + +## Types in Modules + +You may want to provide a type for JavaScript code which does not exist + +```js +function getArrayMetadata(arr) { + return { + length: getArrayLength(arr), + firstObject: arr[0], + }; +} + +module.exports = { + getArrayMetadata, +}; +``` + +This can be described with: + +```ts +export type ArrayMetadata = { + length: number; + firstObject: any | undefined; +}; +export function getArrayMetadata(arr: any[]): ArrayMetadata; +``` + +This example is a good case for [using generics](/docs/handbook/generics.html#generic-types) to provide richer type information: + +```ts +export type ArrayMetadata = { + length: number; + firstObject: ArrType | undefined; +}; + +export function getArrayMetadata( + arr: ArrType[] +): ArrayMetadata; +``` + +Now the type of the array propagates into the `ArrayMetadata` type. + +The types which are exported can then be re-used by consumers of the modules using either `import` or `import type` in TypeScript code or [JSDoc imports](/docs/handbook/jsdoc-supported-types.html#import-types). + +### Namespaces in Module Code + +Trying to describe the runtime relationship of JavaScript code can be tricky. +When the ES Module-like syntax doesn't provide enough tools to describe the exports then you can use `namespaces`. + +For example, you may have complex enough types to describe that you choose to namespace them inside your `.d.ts`: + +```ts +// This represents the JavaScript class which would be available at runtime +export class API { + constructor(baseURL: string); + getInfo(opts: API.InfoRequest): API.InfoResponse; +} + +// This namespace is merged with the API class and allows for consumers, and this file +// to have types which are nested away in their own sections. +declare namespace API { + export interface InfoRequest { + id: string; + } + + export interface InfoResponse { + width: number; + height: number; + } +} +``` + +To understand how namespaces work in `.d.ts` files read the [`.d.ts` deep dive](/docs/handbook/declaration-files/deep-dive.html). + +### Optional Global Usage + +You can use `export as namespace` to declare that your module will be available in the global scope in UMD contexts: + +```ts +export as namespace moduleName; +``` + +## Reference Example + +To give you an idea of how all these pieces can come together, here is a reference `.d.ts` to start with when making a new module + ```ts // Type definitions for [~THE LIBRARY NAME~] [~OPTIONAL VERSION NUMBER~] // Project: [~THE PROJECT NAME~] @@ -21,13 +244,13 @@ permalink: /docs/handbook/declaration-files/templates/module-d-ts.html */ export as namespace myLib; -/*~ If this module has methods, declare them as functions like so. +/*~ If this module exports functions, declare them like so. */ -export function myMethod(a: string): string; -export function myOtherMethod(a: number): number; +export function myFunction(a: string): string; +export function myOtherFunction(a: number): number; /*~ You can declare types that are available via importing the module */ -export interface someType { +export interface SomeType { name: string; length: number; extras?: string[]; @@ -35,18 +258,54 @@ export interface someType { /*~ You can declare properties of the module using const, let, or var */ export const myField: number; +``` -/*~ If there are types, properties, or methods inside dotted names - *~ of the module, declare them inside a 'namespace'. - */ -export namespace subProp { - /*~ For example, given this definition, someone could write: - *~ import { subProp } from 'yourModule'; - *~ subProp.foo(); - *~ or - *~ import * as yourMod from 'yourModule'; - *~ yourMod.subProp.foo(); - */ - export function foo(): void; -} +### Library file layout + +The layout of your declaration files should mirror the layout of the library. + +A library can consist of multiple modules, such as + +``` +myLib + +---- index.js + +---- foo.js + +---- bar + +---- index.js + +---- baz.js +``` + +These could be imported as + +```js +var a = require("myLib"); +var b = require("myLib/foo"); +var c = require("myLib/bar"); +var d = require("myLib/bar/baz"); +``` + +Your declaration files should thus be + +``` +@types/myLib + +---- index.d.ts + +---- foo.d.ts + +---- bar + +---- index.d.ts + +---- baz.d.ts ``` + +### Testing your types + +If you are planning on submitting these changes to DefinitelyTyped for everyone to also use, then we recommend you: + +> 1. Create a new folder in `node_modules/@types/[libname]` +> 2. Create an `index.d.ts` in that folder, and copy the example in +> 3. See where your usage of the module breaks, and start to fill out the index.d.ts +> 4. When you're happy, clone [DefinitelyTyped/DefinitelyTyped](https://github.com/DefinitelyTyped) and follow the instructions in the README. + +Otherwise + +> 1. Create a new file in the root of your source tree: `[libname].d.ts` +> 2. Add `declare module "[libname]" { }` +> 3. Add the template inside the braces of the declare module, and see where your usage breaks diff --git a/packages/documentation/scripts/generateDocsNavigationPerLanguage.js b/packages/documentation/scripts/generateDocsNavigationPerLanguage.js index 74d3dc5e591d..df3fbf29c2f3 100644 --- a/packages/documentation/scripts/generateDocsNavigationPerLanguage.js +++ b/packages/documentation/scripts/generateDocsNavigationPerLanguage.js @@ -67,11 +67,11 @@ const handbookPages = [ { file: "JSX.md" }, { file: "Mixins.md" }, { file: "Modules.md" }, - { file: "Module Resolution.md"}, + { file: "Module Resolution.md" }, { file: "Namespaces.md" }, { file: "Namespaces and Modules.md" }, { file: "Symbols.md" }, - { file: "Triple-Slash Directives.md"}, + { file: "Triple-Slash Directives.md" }, { file: "Type Compatibility.md" }, { file: "Type Inference.md" }, { file: "Variable Declarations.md" }, @@ -103,22 +103,24 @@ const handbookPages = [ "Learn how to write declaration files to describe existing JavaScript. Important for DefinitelyTyped contributions.", chronological: true, items: [ - { file: "declaration files/Introduction.md"}, - { file: "declaration files/By Example.md"}, - { file: "declaration files/Do's and Don'ts.md"}, - { file: "declaration files/Deep Dive.md" }, + { file: "declaration files/Introduction.md" }, + { file: "declaration files/By Example.md" }, { file: "declaration files/Library Structures.md" }, - { title: ".d.ts Templates", + { + title: ".d.ts Templates", items: [ - { file: "declaration files/templates/global.d.ts.md" }, - { file: "declaration files/templates/global-modifying-module.d.ts.md"}, - { file: "declaration files/templates/module.d.ts.md" }, - { file: "declaration files/templates/module-plugin.d.ts.md" }, - { file: "declaration files/templates/module-class.d.ts.md" }, - { file: "declaration files/templates/module-function.d.ts.md" }, - ]}, + { file: "declaration files/templates/module.d.ts.md" }, + { file: "declaration files/templates/module-plugin.d.ts.md" }, + { file: "declaration files/templates/module-class.d.ts.md" }, + { file: "declaration files/templates/module-function.d.ts.md" }, + { file: "declaration files/templates/global.d.ts.md" }, + { file: "declaration files/templates/global-modifying-module.d.ts.md" }, + ] + }, + { file: "declaration files/Do's and Don'ts.md" }, + { file: "declaration files/Deep Dive.md" }, { file: "declaration files/Publishing.md" }, - { file: "declaration files/Consumption.md"}, + { file: "declaration files/Consumption.md" }, ], }, { @@ -127,8 +129,8 @@ const handbookPages = [ chronological: true, items: [ { file: "Intro to JS with TS.md", }, - { file:"Type Checking JavaScript Files.md" }, - { file:"JSDoc Reference.md" }, + { file: "Type Checking JavaScript Files.md" }, + { file: "JSDoc Reference.md" }, { file: "declaration files/Creating DTS files From JS.md" }, ], }, @@ -204,7 +206,7 @@ for (const lang of langs) { `); /** @param {{ items?: HandbookNavSubItem[] }} itemable */ - function addItems(itemable) { + function addItems (itemable) { // Lots of 2nd level navs dont have subnav, bail for them if ("items" in itemable === false) return; @@ -307,7 +309,7 @@ writeFileSync( * @property {HandbookNavSubItem[]} items - pages */ -function validateNonEnglishMarkdownFile(info, lang, filepath) { +function validateNonEnglishMarkdownFile (info, lang, filepath) { if (!info.data.permalink.startsWith("/" + lang + "/")) { throw new Error( `Permalink in ${filepath} does not start with '/${lang}/'\n\n` @@ -315,7 +317,7 @@ function validateNonEnglishMarkdownFile(info, lang, filepath) { } } -function validateMarkdownFile(info, filepath) { +function validateMarkdownFile (info, filepath) { // const needed = ["permalink", "oneline", "title"]; const needed = ["permalink", "title"]; const missing = []; @@ -330,13 +332,13 @@ function validateMarkdownFile(info, filepath) { } } -function throwForUnfoundFile(subItem, lang, langInfo) { +function throwForUnfoundFile (subItem, lang, langInfo) { const keys = [...langInfo.keys()]; // prettier-ignore throw new Error(`Could not find the file '${subItem.file}' from the handbook nav in either ${lang} or 'en' - has: ${keys.join(", ")}`); } -function fillReleaseInfo() { +function fillReleaseInfo () { const whatIsNew = handbookPages.find((h) => h.title === "What's New"); const files = readdirSync( join(__dirname, "..", "copy", "en", "release notes") @@ -347,6 +349,6 @@ function fillReleaseInfo() { } } -function toID(str) { +function toID (str) { return str.toLowerCase().replace(/\s/g, "-"); } diff --git a/packages/typescriptlang-org/src/components/layout/main.scss b/packages/typescriptlang-org/src/components/layout/main.scss index d0a3f125790c..d516df892af3 100644 --- a/packages/typescriptlang-org/src/components/layout/main.scss +++ b/packages/typescriptlang-org/src/components/layout/main.scss @@ -116,10 +116,8 @@ html, html.light-theme { } // Style the permalink icon in dark colour-scheme -.raised .markdown .anchor.before svg path { - @media (prefers-color-scheme: dark) { - fill: #fff; - } +.dark-theme .raised .markdown .anchor.before svg path { + fill: #fff; } .main-content-block { diff --git a/packages/typescriptlang-org/src/lib/documentationNavigation.ts b/packages/typescriptlang-org/src/lib/documentationNavigation.ts index 8fb9dda5a0aa..116b6a443b78 100644 --- a/packages/typescriptlang-org/src/lib/documentationNavigation.ts +++ b/packages/typescriptlang-org/src/lib/documentationNavigation.ts @@ -472,26 +472,14 @@ export function getDocumentationNavForLanguage( id: "introduction", permalink: "/docs/handbook/declaration-files/introduction.html", oneline: - "How to write a high-quality TypeScript Ddeclaration (d.ts) file", + "How to write a high-quality TypeScript Declaration (d.ts) file", }, { - title: "By Example", - id: "by-example", + title: "Declaration Reference", + id: "declaration-reference", permalink: "/docs/handbook/declaration-files/by-example.html", oneline: "How to create a d.ts file for a module", }, - { - title: "Do's and Don'ts", - id: "do's-and-don'ts", - permalink: "/docs/handbook/declaration-files/do-s-and-don-ts.html", - oneline: "Recommendations for writing d.ts files", - }, - { - title: "Deep Dive", - id: "deep-dive", - permalink: "/docs/handbook/declaration-files/deep-dive.html", - oneline: "How do d.ts files work, a deep dive", - }, { title: "Library Structures", id: "library-structures", @@ -505,49 +493,61 @@ export function getDocumentationNavForLanguage( items: [ { - title: "global.d.ts", - id: "global.d.ts", + title: "Modules .d.ts", + id: "modules-.d.ts", permalink: - "/docs/handbook/declaration-files/templates/global-d-ts.html", + "/docs/handbook/declaration-files/templates/module-d-ts.html", oneline: "undefined", }, { - title: "global-modifying-module.d.ts", - id: "global-modifying-module.d.ts", + title: "Module: Plugin", + id: "module:-plugin", permalink: - "/docs/handbook/declaration-files/templates/global-modifying-module-d-ts.html", + "/docs/handbook/declaration-files/templates/module-plugin-d-ts.html", oneline: "undefined", }, { - title: "module.d.ts", - id: "module.d.ts", + title: "Module: Class", + id: "module:-class", permalink: - "/docs/handbook/declaration-files/templates/module-d-ts.html", + "/docs/handbook/declaration-files/templates/module-class-d-ts.html", oneline: "undefined", }, { - title: "module-plugin.d.ts", - id: "module-plugin.d.ts", + title: "Module: Function", + id: "module:-function", permalink: - "/docs/handbook/declaration-files/templates/module-plugin-d-ts.html", + "/docs/handbook/declaration-files/templates/module-function-d-ts.html", oneline: "undefined", }, { - title: "module-class.d.ts", - id: "module-class.d.ts", + title: "Global .d.ts", + id: "global-.d.ts", permalink: - "/docs/handbook/declaration-files/templates/module-class-d-ts.html", + "/docs/handbook/declaration-files/templates/global-d-ts.html", oneline: "undefined", }, { - title: "module-function.d.ts", - id: "module-function.d.ts", + title: "Global: Modifying Module", + id: "global:-modifying-module", permalink: - "/docs/handbook/declaration-files/templates/module-function-d-ts.html", + "/docs/handbook/declaration-files/templates/global-modifying-module-d-ts.html", oneline: "undefined", }, ], }, + { + title: "Do's and Don'ts", + id: "do's-and-don'ts", + permalink: "/docs/handbook/declaration-files/do-s-and-don-ts.html", + oneline: "Recommendations for writing d.ts files", + }, + { + title: "Deep Dive", + id: "deep-dive", + permalink: "/docs/handbook/declaration-files/deep-dive.html", + oneline: "How do d.ts files work, a deep dive", + }, { title: "Publishing", id: "publishing", @@ -1104,26 +1104,14 @@ export function getDocumentationNavForLanguage( id: "introduction", permalink: "/docs/handbook/declaration-files/introduction.html", oneline: - "How to write a high-quality TypeScript Ddeclaration (d.ts) file", + "How to write a high-quality TypeScript Declaration (d.ts) file", }, { - title: "By Example", - id: "by-example", + title: "Declaration Reference", + id: "declaration-reference", permalink: "/docs/handbook/declaration-files/by-example.html", oneline: "How to create a d.ts file for a module", }, - { - title: "Do's and Don'ts", - id: "do's-and-don'ts", - permalink: "/docs/handbook/declaration-files/do-s-and-don-ts.html", - oneline: "Recommendations for writing d.ts files", - }, - { - title: "Deep Dive", - id: "deep-dive", - permalink: "/docs/handbook/declaration-files/deep-dive.html", - oneline: "How do d.ts files work, a deep dive", - }, { title: "Library Structures", id: "library-structures", @@ -1137,49 +1125,61 @@ export function getDocumentationNavForLanguage( items: [ { - title: "global.d.ts", - id: "global.d.ts", + title: "Modules .d.ts", + id: "modules-.d.ts", permalink: - "/docs/handbook/declaration-files/templates/global-d-ts.html", + "/docs/handbook/declaration-files/templates/module-d-ts.html", oneline: "undefined", }, { - title: "global-modifying-module.d.ts", - id: "global-modifying-module.d.ts", + title: "Module: Plugin", + id: "module:-plugin", permalink: - "/docs/handbook/declaration-files/templates/global-modifying-module-d-ts.html", + "/docs/handbook/declaration-files/templates/module-plugin-d-ts.html", oneline: "undefined", }, { - title: "module.d.ts", - id: "module.d.ts", + title: "Module: Class", + id: "module:-class", permalink: - "/docs/handbook/declaration-files/templates/module-d-ts.html", + "/docs/handbook/declaration-files/templates/module-class-d-ts.html", oneline: "undefined", }, { - title: "module-plugin.d.ts", - id: "module-plugin.d.ts", + title: "Module: Function", + id: "module:-function", permalink: - "/docs/handbook/declaration-files/templates/module-plugin-d-ts.html", + "/docs/handbook/declaration-files/templates/module-function-d-ts.html", oneline: "undefined", }, { - title: "module-class.d.ts", - id: "module-class.d.ts", + title: "Global .d.ts", + id: "global-.d.ts", permalink: - "/docs/handbook/declaration-files/templates/module-class-d-ts.html", + "/docs/handbook/declaration-files/templates/global-d-ts.html", oneline: "undefined", }, { - title: "module-function.d.ts", - id: "module-function.d.ts", + title: "Global: Modifying Module", + id: "global:-modifying-module", permalink: - "/docs/handbook/declaration-files/templates/module-function-d-ts.html", + "/docs/handbook/declaration-files/templates/global-modifying-module-d-ts.html", oneline: "undefined", }, ], }, + { + title: "Do's and Don'ts", + id: "do's-and-don'ts", + permalink: "/docs/handbook/declaration-files/do-s-and-don-ts.html", + oneline: "Recommendations for writing d.ts files", + }, + { + title: "Deep Dive", + id: "deep-dive", + permalink: "/docs/handbook/declaration-files/deep-dive.html", + oneline: "How do d.ts files work, a deep dive", + }, { title: "Publishing", id: "publishing", diff --git a/packages/typescriptlang-org/src/templates/pages/docs/handbook/index.tsx b/packages/typescriptlang-org/src/templates/pages/docs/handbook/index.tsx index 65c10d795ce9..9e942251062e 100644 --- a/packages/typescriptlang-org/src/templates/pages/docs/handbook/index.tsx +++ b/packages/typescriptlang-org/src/templates/pages/docs/handbook/index.tsx @@ -46,6 +46,7 @@ const HandbookIndex: React.FC = (props) => {
    {navRoot.items && navRoot.items.map(item => { const path = item.permalink! + if (item.items) return null return
  • {item.title}