From 48ac7f9bbd4a83062c94d8d364fe6dc42f23247b Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Sun, 3 Jul 2016 22:48:05 -0700 Subject: [PATCH 01/29] Intiial commit of @RyanCavanaugh's documentation --- .../Adding to DefinitelyTyped.md | 24 ++ pages/declaration files/By Example.md | 254 +++++++++++++ pages/declaration files/Deep Dive.md | 209 +++++++++++ pages/declaration files/Do's and Don'ts.md | 208 +++++++++++ pages/declaration files/Introduction.md | 46 +++ pages/declaration files/Library Structures.md | 352 ++++++++++++++++++ pages/declaration files/presentation.md | 70 ++++ .../templates/global-modifying-module.d.ts | 33 ++ .../templates/global-plugin.d.ts | 25 ++ pages/declaration files/templates/global.d.ts | 62 +++ .../templates/module-class.d.ts | 47 +++ .../templates/module-function.d.ts | 56 +++ .../templates/module-plugin.d.ts | 34 ++ pages/declaration files/templates/module.d.ts | 45 +++ pages/declaration files/todo.md | 32 ++ 15 files changed, 1497 insertions(+) create mode 100644 pages/declaration files/Adding to DefinitelyTyped.md create mode 100644 pages/declaration files/By Example.md create mode 100644 pages/declaration files/Deep Dive.md create mode 100644 pages/declaration files/Do's and Don'ts.md create mode 100644 pages/declaration files/Introduction.md create mode 100644 pages/declaration files/Library Structures.md create mode 100644 pages/declaration files/presentation.md create mode 100644 pages/declaration files/templates/global-modifying-module.d.ts create mode 100644 pages/declaration files/templates/global-plugin.d.ts create mode 100644 pages/declaration files/templates/global.d.ts create mode 100644 pages/declaration files/templates/module-class.d.ts create mode 100644 pages/declaration files/templates/module-function.d.ts create mode 100644 pages/declaration files/templates/module-plugin.d.ts create mode 100644 pages/declaration files/templates/module.d.ts create mode 100644 pages/declaration files/todo.md diff --git a/pages/declaration files/Adding to DefinitelyTyped.md b/pages/declaration files/Adding to DefinitelyTyped.md new file mode 100644 index 000000000..51888edf3 --- /dev/null +++ b/pages/declaration files/Adding to DefinitelyTyped.md @@ -0,0 +1,24 @@ +# Creating a New DefinitelyTyped File + +This page will walk you through how to create a new folder in DefinitelyTyped. + +## Create the Folder + +Naming + +## Copy from _template + +## Rename `-tests.ts` + +## Modify tsconfig.json + +Use the template, modify files param, leave remainder untouched + +## Write Your File + +## Test for Compilation + +## Test for Conformance + +## Test for Breaks + diff --git a/pages/declaration files/By Example.md b/pages/declaration files/By Example.md new file mode 100644 index 000000000..481c28eef --- /dev/null +++ b/pages/declaration files/By Example.md @@ -0,0 +1,254 @@ +# Definition Files by Example + +## Introduction + +The purpose of this guide is to teach you how to write a high-quality definition file. +This guide is structured by showing an example *usage* and *documentation*, + and explaining how to write the corresponding declaration. + +These examples are ordered in approximately increasing order of complexity. + + + + + + +- [The Examples](#the-examples) + - [Global variable](#global-variable) + - [Global function](#global-function) + - [Object with Properties](#object-with-properties) + - [Overloaded function](#overloaded-function) + - [Reusable Types (Global)](#reusable-types-global) + - [Classes](#classes) + + + + +## 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 invoke the function `greet` with a string to show a greeting to the user. + +*Code* +``` +greet('hello, world'); +``` + +*Declaration* + +Use `declare function` to declare functions. +```ts +declare function greet(greeting: string): void; +``` + +### Objects with Properties + +*Documentation* +> The global variable `myLib` has a function `makeGreeting` for creating greetings, +> and a property `numberOfGreetings` indicating the number of greetings made so far. + +*Code* +```ts +var result = myLib.makeGreeting('hello, world'); +console.log('The computed greeting is:' + result); +var count = myLib.numberOfGreetings; +``` + +*Declaration* + +Use `declare namespace` to describe types or values accessed by dotted notation. +```ts +declare namespace myLib { + function makeGreeting(s: string): string; + let numberOfGreetings: number; +} +``` + +### Overloaded functions + +*Documentation* +> The `getWidget` function accepts a number and return a Widget, or accepts a string and returns a Widget array + +*Code* +```ts +let x: Widget = getWidget(43); +let arr = getWidget('all of them'); // arr: Widget[] +``` + +*Declaration* +```ts +declare function getWidget(n: number): Widget; +declare function getWidget(s: string): Widget[]; +``` + +### Reusable Types (interfaces) + +*Documentation* +> When specifying a greeting, you must pass a GreetingSettings object. +> This object has the following properties: +> * greeting: Mandatory string +> * duration: Optional length of time (in milliseconds) +> * color: Optional string, e.g. '#ff00ff' + +*Code* +```ts +greet({ + greeting: 'hello world', + duration: 4000 +}); +``` + +*Declaration* + +Use `interface` to define a type with properties. +```ts +interface GreetingSettings { + greeting: string; + duration?: number; + color?: string; +} +declare function greet(setting: GreetingSettings): void; +``` + +### Reusable Types (type aliases) + +*Documentation* +> Anywhere a greeting is expected, you can provide a `string`, +> a function returning a `string`, or a `Greeter` class. + +*Code* +```ts +function getGreeting() { + return 'howdy'; +} +class MyGreeter extends Greeter { } + +greet('hello'); +greet(getGreeting); +greet(new MyGreeter()); +``` + +*Declaration* + +You can use a type alias to make a shorthand for a type: +```ts +type GreetingLike = string | (() => string) | Greeting; + +declare function greet(g: GreetingLike): void; +``` + +### Organizing Types + +*Documentation* +> The `greeter` object can log to a file, or display an alert. +> You can provide LogOptions to `.log(...)` or alert options to `.alert(...)` + +*Code* +```ts +const g = new Greeter('Hello'); +g.log({ verbose: true }); +g.alert({ modal: false, title: 'Current Greeting' }); +``` + +*Declaration* + +Use namespaces to organize types. +```ts +declare namespace GreetingLib { + interface LogOptions { + verbose?: boolean; + } + interface AlertOptions { + modal: boolean; + title?: string; + color?: string; + } +} +``` + +You can also created nested namespaces in one declaration: +```ts +declare namespace GreetingLib.Options { + // Refer to via GreetingLib.Options.Log + interface Log { + verbose?: boolean; + } + interface Alert { + modal: boolean; + title?: string; + color?: string; + } +} +``` + +### Classes + +*Documentation* +> You can create a greeter by instantiating the `Greeter` object, +> or create a customized greeter by extending from it. + +*Code* +```ts +const myGreeter = new Greeter('hello, world'); +myGreeter.greeting = 'howdy'; +myGreeter.showGreeting(); + +class SpecialGreeter extends Greeter { + constructor() { + super('Very special greetings'); + } +} +``` + +*Declaration* +Use `declare class` to describe a class or classlike object. +Classes can have properties and methods as well as a constructor. +```ts +declare class Greeter { + constructor(greeting: string); + + greeting: string; + showGreeting(): void; +} +``` + + diff --git a/pages/declaration files/Deep Dive.md b/pages/declaration files/Deep Dive.md new file mode 100644 index 000000000..cdd89668c --- /dev/null +++ b/pages/declaration files/Deep Dive.md @@ -0,0 +1,209 @@ +# Definition 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. +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 + by understanding some key concepts of how TypeScript works. + +### Types + +If you're reading this guide, you probably already roughly know what a type in TypeScript is. +To be more explicit, though, a *type* is introduced with: + * A type alias declaration (`type sn = number | string;`) + * An interface declaration (`interface I { x: number[]; }`) + * A class declaration (`class C { }`) + * An enum declaration (`enum E { A, B, C }`) + * An `import` declaration which refers to a type + +Each of these declaration forms creates a new type name. + +### Values + +As with types, you probably already understand what a value is. +Values are runtime names that we can reference in expressions. +For example `let x = 5;` creates a value called `x`. + +Again, being explicit, the following things create values: + * `let`, `const`, and `var` declarations + * A `namespace` or `module` declaration which contains a value + * An `enum` declaration + * A `class` declaration + * An `import` declaration which refers to a value + * A `function` declaration + +### Namespaces + +Types can exist in *namespaces*. +For example, if we have the declaration `let x: A.B.C`, + we say that the type `C` comes from the `A.B` namespace. + +This distinction is subtle and important -- here, `A.B` is not necessarily a type or a value. + +## Simple Combinations: One name, multiple meanings + +Given a name `A`, we might find up to three different meanings for `A`: a type, a value or a namespace. +How the name is interpreted depends on the context in which it is used. +For example, in the declaration `let m: A.A = A;`, + `A` is used first as a namespace, then as a type name, then as a value. +These meanings might end up referring to entirely different declarations! + +This may seem confusing, but it's actually very convenient as long as we don't excessively overload things. +Let's look at some useful aspects of this combining behavior. + +### Built-in Combinations + +Astute readers will notice that, for example, `class` appeared in both the *type* and *value* lists. +The declaration `class C { }` creates two things: + a *type* `C` which refers to the instance shape of the class, + and a *value* `C` which refers to the constructor function of the class. +Enum declarations behave similarly. + +### User Combinations + +Let's say we wrote a module file `foo.d.ts`: +```ts +export var SomeVar: { a: SomeType }; +export interface SomeVar { + count: number; +} +``` +Then consumed it: +```ts +import * as foo from './foo'; +let x: foo.SomeType = foo.SomeVar.a; +console.log(x.count); +``` +This works well enough, but we might imagine that `SomeType` and `SomeVar` were very closely related + such that you'd like them to have the same name. +We can use combining to present these two different objects (the value and the type) under the same name `Bar`: +```ts +export var Bar: { a: Bar }; +export interface Bar { + count: number; +} +``` +This presents a very good opportunity for destructuring in the consuming code: +```ts +import { Bar } from './foo'; +let x: Bar = Bar.a; +console.log(x.count); +``` +Again, we've used `Bar` as both a type and a value here. +Note that we didn't have to declare the `Bar` value as being of the `Bar` type -- they're independent. + +## Advanced Combinations + +Some kinds of declarations can be combined across multiple declarations. +For example, `class C { }` and `interface C { }` can co-exist and both contribute properties to the `C` types. + +This is legal as long as it does not create a conflict. +A general rule of thumb is that values always conflict with other values of the same name unless they are declared as `namespace`s, + types will conflict if they are declared with a type alias declaration (`type s = string`), + and namespaces never conflict. + +Let's see how this can be used. + +### Adding using an `interface` + +We can add additional members to an `interface` with another `interface` declaration: +```ts +interface Foo { + x: number; +} +// ... elsewhere ... +interface Foo { + y: number; +} +let a: Foo = ...; +console.log(a.x + a.y); // OK +``` +This also works with classes: +```ts +class Foo { + x: number; +} +// ... elsewhere ... +interface Foo { + y: number; +} +let a: Foo = ...; +console.log(a.x + a.y); // OK +``` +Note that we cannot add to type aliases (`type s = string;`) using an interface. + +### Adding using a `namespace` + +A `namespace` declaration can be used to add new types, values, and namespaces in any way which does not create a conflict. + +For example, we can add a static member to a class: +```ts +class C { +} +// ... elsewhere ... +namespace C { + export let x: number; +} +let y = C.x; // OK +``` +Note that in this example, we added a value to the *static* side of `C` (its constructor function). +This is because we added a *value*, and the container for all values is another value + (types are contained by namespaces, and namespaces are contained by other namespaces). + +We could also add a namespaced type to a class: +```ts +class C { +} +// ... elsewhere ... +namespace C { + export interface D { } +} +let y: C.D; // OK +``` +In this example, there wasn't a namespace `C` until we wrote the `namespace` declaration for it. +The meaning `C` as a namespace doesn't conflict with the value or type meanings of `C` created by the class. + +Finally, we could perform many different merges using `namespace` declarations. +This isn't a particularly realistic example, but shows all sorts of interesting behavior: +```ts +namespace X { + export interface Y { } + export class Z { } +} + +// ... elsewhere ... +namespace X { + export var Y: number; + export namespace Z { + export class C { } + } +} +type X = string; +``` +In this example, the first block creates the following name meanings: + * A value `X` (because the `namespace` declaration contains a value, `Z`) + * A namespace `X` (because the `namespace` declaration contains a type, `Y`) + * A type `Y` in the `X` namespace + * A type `Z` in the `X` namespace (the instance shape of the class) + * A value `Z` that is a property of the `X` value (the constructor function of the class) + +The second block creates the following name meanings: + * A value `Y` (of type `number`) that is a property of the `X` value + * A namespace `Z` + * A value `Z` that is a property of the `X` value + * A type `C` in the `X.Z` namespace + * 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. + +TODO: Write more on that. diff --git a/pages/declaration files/Do's and Don'ts.md b/pages/declaration files/Do's and Don'ts.md new file mode 100644 index 000000000..c96ad4ccf --- /dev/null +++ b/pages/declaration files/Do's and Don'ts.md @@ -0,0 +1,208 @@ +# Do's and Don'ts + +## General Types + +### `Number`, `String`, `Boolean`, and `Object` + +*Don't* ever use the types `Number`, `String`, `Boolean`, or `Object`. +These types refer to non-primitive boxed objects that are almost never used appropriately in JavaScript code. +```ts +/* WRONG */ +function reverse(s: String): String; +``` + +*Do* use the types `number`, `string`, and `boolean`. +```ts +/* OK */ +function reverse(s: string): string; +``` + +If you're tempted to use the type `Object`, consider using `any` instead. +There is currently no way in TypeScript to specify an object that is "not a primitive". + + +## Generics + +*Don't* ever have a generic type which doesn't use its type parameter. +TODO: Link to FAQ + +TODO: More + +## Callback Types + +### Return Types of Callbacks + + + +*Don't* use the return type `any` for callbacks whose value will be ignored: +```ts +/* WRONG */ +function fn(x: () => any) { + x(); +} +``` + +*Do* use the return type `void` for callbacks whose value will be ignored: +```ts +/* OK */ +function fn(x: () => void) { + x(); +} +``` + +*Why*: Using `void` is safer because it prevents you from accidently using the return value of `x` in an unchecked way: +```ts +function fn(x: () => void) { + var k = x(); // oops! meant to do something else + k.doSomething(); // error, but would be OK if the return type had been 'any' +} +``` + +### Optional Parameters in Callbacks + +*Don't* use optional parameters in callbacks unless you really mean it: +```ts +/* WRONG */ +interface Fetcher { + getObject(done: (data: any, elapsedTime?: number) => void): void; +} +``` +This has a very specific meaning: the `done` callback might be invoked with 1 argument or might be invoked with 2 arguments. +The author probably intended to say that the callback might not care about the `elapsedTime` parameter, + but there's no need to make the parameter optional to accomplish this -- + it's always legal to provide a callback that accepts fewer arguments. + +*Do* write callback parameters as non-optional: +```ts +/* OK */ +interface Fetcher { + getObject(done: (data: any, elapsedTime: number) => void): void; +} +``` + +### Overloads and Callbacks + +*Don't* write separate overloads that differ only on callback arity: +```ts +/* WRONG */ +declare function beforeAll(action: () => void, timeout?: number): void; +declare function beforeAll(action: (done: DoneFn) => void, timeout?: number): void; +``` + +*Do* write a single overload using the maximum arity: +```ts +/* OK */ +declare function beforeAll(action: (done: DoneFn) => void, timeout?: number): void; +``` + +*Why*: It's always legal for a callback to disregard a parameter, so there's no need for the shorter overload. +Providing a shorter callback first allows incorrectly-typed functions to be passed in because they match the first overload. + +## Function Overloads + +### Ordering + +*Don't* put more general overloads before more specific overloads: +```ts +/* WRONG */ +declare function fn(x: any): any; +declare function fn(x: HTMLElement): number; +declare function fn(x: HTMLDivElement): string; + +var myElem: HTMLDivElement; +var x = fn(myElem); // x: any, wat? +``` + +*Do* sort overloads by putting the more general signatures after more specific signatures: +```ts +/* OK */ +declare function fn(x: HTMLDivElement): string; +declare function fn(x: HTMLElement): number; +declare function fn(x: any): any; + +var myElem: HTMLDivElement; +var x = fn(myElem); // x: string, :) +``` + +*Why*: TypeScript chooses the *first matching overload* when resolving function calls. +When an earlier overload is "more general" than a later one, the later one is effectively hidden and cannot be called. + +### Use Optional Parameters + +*Don't* write several overloads that differ only in trailing parameters: +```ts +/* WRONG */ +interface Moment { + diff(b: MomentComparable): number; + diff(b: MomentComparable, unitOfTime: string): number; + diff(b: MomentComparable, unitOfTime: string, round: boolean): number; +} +``` + +*Do* use optional parameters whenever possible: +```ts +/* OK */ +interface Moment { + diff(b: MomentComparable, unitOfTime?: string, round?: boolean): number; +} +``` + +Note that this collapsing should only occur when all overloads have the same return type. + +*Why*: This is important for two reasons. + +TypeScript resolves signature compatibility by seeing if any signature of the target can be invoked with the arguments of the source, + *and extraneuous arguments are allowed*. +This code, for example, exposes a bug only when the signature is correctly written using optional parameters: +```ts +function fn(x: (a: string, b: number, c: number) => void) { } +var x: Moment; +// When written with overloads, OK -- used first overload +// When written with optionals, correctly an error +fn(x.diff); +``` + +The second reason is when a consumer uses the "strict null checking" feature of TypeScript. Because unspecified parameters appear as `undefined` in JavaScript, it's usually fine to pass an explicit `undefined` to a function with optional arguments. +This code, for example, should be OK under strict nulls: +```ts +var x: Moment; +// When written with overloads, incorrectly an error because of passing 'undefined' to 'string' +// When written with optionals, correctly OK +x.diff(something, someOtherThing ? undefined : "hour"); +``` + +### Use Union Types + +*Don't* write overloads that differ by type in only one argument position: +```ts +/* WRONG */ +interface Moment { + utcOffset(): number; + utcOffset(b: number): Moment; + utcOffset(b: string): Moment; +} +``` + +*Do* use union types whenver possible: +```ts +/* OK */ +interface Moment { + utcOffset(): number; + utcOffset(b: number|string): Moment; +} +``` + +Note that we didn't make `b` optional here because the return types of the signatures differ. + +*Why*: This is important for people who are "passing through" a value to your function: +```ts +function fn(x: string): void; +function fn(x: number): void; +function fn(x: number|string) { + // When written with separate overloads, incorrectly an error + // When written with union types, correctly OK + return moment().utcOffset(x); +} +``` + + diff --git a/pages/declaration files/Introduction.md b/pages/declaration files/Introduction.md new file mode 100644 index 000000000..44fffb54e --- /dev/null +++ b/pages/declaration files/Introduction.md @@ -0,0 +1,46 @@ +# .d.ts File Writing: A Complete Guide + +## Introduction + +This guide is designed to teach you how to write a high-quality TypeScript Declaration File. + +In this guide, we'll assume basic familiarity with the TypeScript language. +If you haven't already, you should read the [https://www.typescriptlang.org/docs/handbook/basic-types.html](TypeScript Handbook) + to familiarize yourself with basic concepts, especially types and namespaces. + + +## Sections + +The guide is broken down into the following sections. + +### Library Structures + +The [Library Structures] guide helps you understand common library formats and how to write a correct declaration file for each formats. +If you're editing an existing file, you probably don't need to read this section. +Authors of new declaration files must read this section to properly understand how the format of the library influences the writing of the declaration file. + +### Do's and Don'ts + +Many common mistakes in declaration files can be easily avoided. +The [Do's and Don'ts] section identifies common errors, + desscribes how to detect them, + and how to fix them. +Everyone should read this section to help themselves avoid common mistakes. + +### By Example + +Many times, we are faced with writing a declaration file when we only have examples of the underlying library to guide us. +The [By Example] 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. + +### Deep Dive + +For seasoned authors interested in the underlying mechanics of how declaration files work, + the [Deep Dive] 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 the `templates` directory, 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] to figure out which template file to use. diff --git a/pages/declaration files/Library Structures.md b/pages/declaration files/Library Structures.md new file mode 100644 index 000000000..f624a1b4e --- /dev/null +++ b/pages/declaration files/Library Structures.md @@ -0,0 +1,352 @@ +# Structuring: Overview + +Broadly speaking, the way you *structure* your definition 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 definition file to match it. +This guide covers how to identify common library patterns, + and how to write definition files which correspond to that pattern. + +Each type of major library structuring pattern has a corresponding file in the `templates` directory. +You can start with these templates to help you get going faster. + +# Identifying Kinds of Libraries + +First, we'll review the kinds of libraries TypeScript definition files can represent. +We'll briefly show how each kind of library is *used*, + how it is *written*, + and list some example libraries from the real world. + +Identifying the structure of a library is the first step in writing its definition file. +We'll give hints on how to identify structure both based on its *usage* and its *code*. +Depending on the library's documentation and organization, one might be easier than the other. +We recommend using whichever is more comfortable to you. + +## *global* + +A *global* library is one that can be accessed from the global scope (i.e. without using any form of `import`). +Many libraries simply expose one or more global variables for use. +For example, if you were using jQuery, the `$` variable can be used by simply referring to it: +```ts +$(() => { console.log('hello!'); } ); +``` + +You'll usually see guidance in the documentation of a global library of how to use the library in a script tag: +```html + +``` + +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 definition 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/nodejs-style imports of the form `var fs = require('fs');` + * Calls to `define(...)` + * Documentation describing how to `require` 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. + +### Template + +The template file `global.d.ts` defines an example library `myLib`. +Be sure to read the "Preventing Name Conflicts" footnote. + +## *module* + +Some libraries only work in a module loader environment. +For example, because `express` only works in NodeJS, + it must be loaded using the CommonJS `require` function. + +ECMAScript 2016 (also known as ES2015, ECMAScript 6, ES6), CommonJS, and RequireJS have similar notions of *importing* a *module*. +In JavaScript CommonJS (nodejs), for example, you would write +```ts +var fs = require('fs'); +``` +In TypeScript or ES6, the `import` keyword serves the same purpose: +```ts +import fs = require('fs'); +``` + +You'll typically see module libraries include one of these lines in their documentation: +```js +var someLib = require('someLib'); +``` +or +```ts +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 + +Module 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 Module Libraries + +Many popular nodejs libraries are in the module family, such as `express`, `gulp`, and `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). +Many popular libraries, such as `moment`, are written this way. +For example, in nodejs, you would write: +```ts +import moment = require('moment'); +console.log(moment.format()); +``` +whereas in a vanilla browser environment you would write: +```ts +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(['b'], factory); + } else if (typeof module === 'object' && module.exports) { + module.exports = factory(require('b')); + } else { + root.returnExports = factory(root.b); + } +}(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 nodejs" example showing `require` + and a "Using in browser" example showing using a ` ``` @@ -43,30 +45,33 @@ Before writing a global definition file, make sure the library isn't actually UM Global library code is usually extremely simple. A global "Hello, world" library might look like this: + ```js function createGreeting(s) { - return 'Hello, ' + s; + return 'Hello, ' + s; } ``` + or like this: + ```js window.createGreeting = function(s) { - return 'Hello, ' + 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 +* 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/nodejs-style imports of the form `var fs = require('fs');` - * Calls to `define(...)` - * Documentation describing how to `require` the library +* Checks for, or usage of, module loaders like `require` or `define` +* CommonJS/nodejs-style imports of the form `var fs = require('fs');` +* Calls to `define(...)` +* Documentation describing how to `require` the library ### Examples of Global Libraries @@ -87,22 +92,28 @@ For example, because `express` only works in NodeJS, ECMAScript 2016 (also known as ES2015, ECMAScript 6, ES6), CommonJS, and RequireJS have similar notions of *importing* a *module*. In JavaScript CommonJS (nodejs), for example, you would write + ```ts var fs = require('fs'); ``` + In TypeScript or ES6, the `import` keyword serves the same purpose: + ```ts import fs = require('fs'); ``` You'll typically see module libraries include one of these lines in their documentation: + ```js var someLib = require('someLib'); ``` + or + ```ts define(..., ['someLib'], function(someLib) { - + }); ``` @@ -113,13 +124,13 @@ As with global modules, you might see these examples in the documentation of a U Module 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` +* 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` +* Assignments to properties of `window` or `global` ### Examples of Module Libraries @@ -131,19 +142,23 @@ 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`, are written this way. For example, in nodejs, you would write: + ```ts import moment = require('moment'); console.log(moment.format()); ``` + whereas in a vanilla browser environment you would write: + ```ts console.log(moment.format()); ``` ### Identifying a UMD library -(UMD modules)[https://github.com/umdjs/umd] check for the existence of a module loader environment. +[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) { @@ -154,7 +169,7 @@ This is an easy-to-spot pattern that looks something like this: root.returnExports = factory(root.b); } }(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, @@ -174,19 +189,23 @@ There are three templates available for modules, `module.d.ts`, `module-class.d.ts` and `module-callable.d.ts`. Use `module-callable.d.ts` if your module can be *called* like a function: + ```ts 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" Use `module-class.d.ts` if your module can be *constructed* using `new`: + ```ts var x = require('bar'); // Note: using 'new' operator on the imported variable var y = new x('hello'); ``` + The same footnote applies to these modules. If your module is not callable or constructable, use the `module.d.ts` file. @@ -215,6 +234,7 @@ For example, some libraries add new functions to `Array.prototype` or `String.pr Global plugins are generally easy to identify from their documentation. You'll see examples that look like this: + ```ts var x = 'hello, world'; // Creates new methods on built-in types @@ -242,6 +262,7 @@ 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: + ```ts // 'require' call that doesn't use its return value var unused = require('magic-string-time'); @@ -268,16 +289,19 @@ There are several kinds of dependencies you might have. ## Dependencies on Global Libraries If your library depends on a global library, use a `/// function getThing(): someLib.thing; ``` + This syntax is the same regardless if your library is global, a module, or UMD ## Dependencies on Modules If your library depends on a module, use an `import` statement: + ```ts import * as moment from 'moment'; @@ -289,6 +313,7 @@ function getThing(): moment; ### From a Global Library If your global library depends on a UMD module, use a `/// @@ -298,11 +323,12 @@ function getThing(): moment; ### From a Module or UMD Library If your module or UMD library depends on a UMD library, use an `import` statement: + ```ts import * as someLib from 'someLib'; ``` -Do *not* use a `/// `@types` transition - * Rename `scripts` to `_scripts` - * Create and finish `_template` documentation and folder - * Ensure no `notNeeded` / `external` / local conflicts (already done?) - * Warn in README.md if `noImplicitAny` is off - * Include "last updated" date in README.md - * Figure out what to do with DT issue backlog - * Create bugs for any remaining bad-format files - * Endorse in README.md if `strictNullChecks` is on - * Add stat reporting on how many files are still `noImplicitAny: false` - * Eventually: validate all `tsconfig.json` files for conformance - * Add stat reporting on how many files are `strictNullChecks` - * Include this metadata in `package.json` so we can warn/bless - * Support moving authors to sidecar file in case list gets too long - - -Random thoughts - - * Game-ify DT -- e.g. what if definition files were awarded gold / silver / bronze medals? - * Platinum: Uses string enums, etc (hand-validated) - * Gold: Strict null checked - * Silver: JSDoc on 60%+ of members - * Bronze: No use of `any` - * Identify popular non-gold libraries, TypeScript team upgrades 1 / week - * Use to improve search relevance - * Send PRs of gold+-quality .d.ts files to underlying package's github pages to add badges - * Prizes? Bounties? What would $10,000 of .d.ts upgrades look like? - * Funding pitch: Easily saves us 2 weeks of work, great PR? - * From cf3cad9816c6992c817c4c8470b27aa722b908a2 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Sun, 3 Jul 2016 23:53:07 -0700 Subject: [PATCH 03/29] Add links --- pages/declaration files/Do's and Don'ts.md | 7 +++-- pages/declaration files/Introduction.md | 10 +++---- pages/declaration files/Library Structures.md | 28 +++++++++---------- 3 files changed, 23 insertions(+), 22 deletions(-) diff --git a/pages/declaration files/Do's and Don'ts.md b/pages/declaration files/Do's and Don'ts.md index bf3b65998..5055a8875 100644 --- a/pages/declaration files/Do's and Don'ts.md +++ b/pages/declaration files/Do's and Don'ts.md @@ -26,9 +26,9 @@ There is currently no way in TypeScript to specify an object that is "not a prim ## Generics *Don't* ever have a generic type which doesn't use its type parameter. -TODO: Link to FAQ +See more details in [TypeScript FAQ page](https://github.com/Microsoft/TypeScript/wiki/FAQ#why-doesnt-type-inference-work-on-this-interface-interface-foot---). -TODO: More + ## Callback Types @@ -177,7 +177,8 @@ var x: Moment; fn(x.diff); ``` -The second reason is when a consumer uses the "strict null checking" feature of TypeScript. Because unspecified parameters appear as `undefined` in JavaScript, it's usually fine to pass an explicit `undefined` to a function with optional arguments. +The second reason is when a consumer uses the "strict null checking" feature of TypeScript. +Because unspecified parameters appear as `undefined` in JavaScript, it's usually fine to pass an explicit `undefined` to a function with optional arguments. This code, for example, should be OK under strict nulls: ```ts diff --git a/pages/declaration files/Introduction.md b/pages/declaration files/Introduction.md index b49929d78..df6dcd1de 100644 --- a/pages/declaration files/Introduction.md +++ b/pages/declaration files/Introduction.md @@ -14,14 +14,14 @@ The guide is broken down into the following sections. ### Library Structures -The [Library Structures] guide helps you understand common library formats and how to write a correct declaration file for each formats. +The [Library Structures](./Library Structures.md) guide helps you understand common library formats and how to write a correct declaration file for each formats. If you're editing an existing file, you probably don't need to read this section. Authors of new declaration files must read this section to properly understand how the format of the library influences the writing of the declaration file. ### Do's and Don'ts Many common mistakes in declaration files can be easily avoided. -The [Do's and Don'ts] section identifies common errors, +The [Do's and Don'ts](./Do's and Don'ts.md) section identifies common errors, desscribes how to detect them, and how to fix them. Everyone should read this section to help themselves avoid common mistakes. @@ -29,17 +29,17 @@ Everyone should read this section to help themselves avoid common mistakes. ### By Example Many times, we are faced with writing a declaration file when we only have examples of the underlying library to guide us. -The [By Example] section shows many common API patterns and how to write declarations for each of them. +The [By Example](./By Example.md) 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. ### Deep Dive For seasoned authors interested in the underlying mechanics of how declaration files work, - the [Deep Dive] section explains many advanced concepts in declaration writing, + the [Deep Dive](./Deep Dive.md) 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 the `templates` directory, 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] to figure out which template file to use. +Refer to the documentation in [Library Structures](./Library Structures.md) to figure out which template file to use. diff --git a/pages/declaration files/Library Structures.md b/pages/declaration files/Library Structures.md index 5626a4555..b51425004 100644 --- a/pages/declaration files/Library Structures.md +++ b/pages/declaration files/Library Structures.md @@ -6,7 +6,7 @@ There are many ways of offering a library for consumption in JavaScript, This guide covers how to identify common library patterns, and how to write definition files which correspond to that pattern. -Each type of major library structuring pattern has a corresponding file in the `templates` directory. +Each type of major library structuring pattern has a corresponding file in the [`templates`](./templates) directory. You can start with these templates to help you get going faster. # Identifying Kinds of Libraries @@ -25,7 +25,7 @@ We recommend using whichever is more comfortable to you. A *global* library is one that can be accessed from the global scope (i.e. without using any form of `import`). Many libraries simply expose one or more global variables for use. -For example, if you were using jQuery, the `$` variable can be used by simply referring to it: +For example, if you were using [jQuery](https://jquery.com/), the `$` variable can be used by simply referring to it: ```ts $(() => { console.log('hello!'); } ); @@ -81,7 +81,7 @@ However, libraries that are small and require the DOM (or have *no* dependencies ### Template -The template file `global.d.ts` defines an example library `myLib`. +The template file [`global.d.ts`](./templates/global.d.ts) defines an example library `myLib`. Be sure to read the "Preventing Name Conflicts" footnote. ## *module* @@ -134,13 +134,13 @@ They will rarely have: ### Examples of Module Libraries -Many popular nodejs libraries are in the module family, such as `express`, `gulp`, and `request`. +Many popular nodejs 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). -Many popular libraries, such as `moment`, are written this way. +Many popular libraries, such as [`moment`](http://momentjs.com/), are written this way. For example, in nodejs, you would write: ```ts @@ -181,14 +181,14 @@ Documentation for UMD libraries will also often demonstrate a "Using in nodejs" ### Examples of UMD libraries Most popular libraries are now available as UMD packages. -Examples include `jquery`, `moment`, `lodash`, and many more. +Examples include [`jquery`](https://jquery.com/), [`moment`](http://momentjs.com/), [`lodash`](https://lodash.com/), and many more. ### Template There are three templates available for modules, - `module.d.ts`, `module-class.d.ts` and `module-callable.d.ts`. + [`module.d.ts`](./templates/module.d.ts), [`module-class.d.ts`](./templates/module-class.d.ts) and [`module-function.d.ts`](./templates/module-function.d.ts). -Use `module-callable.d.ts` if your module can be *called* like a function: +Use [`module-function.d.ts`](./templates/module-function.d.ts) if your module can be *called* like a function: ```ts var x = require('foo'); @@ -196,9 +196,9 @@ var x = require('foo'); var y = x(42); ``` -Be sure to read the footnote "The Impact of ES6 on Module Call Signatures" +Be sure to read the footnote ["The Impact of ES6 on Module Call Signatures"](#) -Use `module-class.d.ts` if your module can be *constructed* using `new`: +Use [`module-class.d.ts`](./templates/module-class.d.ts) if your module can be *constructed* using `new`: ```ts var x = require('bar'); @@ -208,7 +208,7 @@ var y = new x('hello'); The same footnote applies to these modules. -If your module is not callable or constructable, use the `module.d.ts` file. +If your module is not callable or constructable, use the [`module.d.ts`](./templates/module.d.ts) file. ## *Module Plugin* or *UMD Plugin* @@ -220,7 +220,7 @@ For the purposes of writing a definition file, you'll write the same code ### Template -Use the `module-plugin.d.ts` template. +Use the [`module-plugin.d.ts`](./templates/module-plugin.d.ts) template. ## *Global Plugin* @@ -247,7 +247,7 @@ console.log(y.reverseAndSort()); ### Template -Use the `global-plugin.d.ts` template. +Use the [`global-plugin.d.ts`](./templates/global-plugin.d.ts) template. ## *Global-modifying Modules* @@ -280,7 +280,7 @@ console.log(y.reverseAndSort()); ### Template -Use the `global-modifying-module.d.ts` template. +Use the [`global-modifying-module.d.ts`](./templates/global-modifying-module.d.ts) template. # Consuming Dependencies From f83215b2ddc631ab4a3d19832b65e30c8b33f041 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Sun, 3 Jul 2016 23:53:42 -0700 Subject: [PATCH 04/29] Remove unused files --- .../Adding to DefinitelyTyped.md | 23 ------------------- 1 file changed, 23 deletions(-) delete mode 100644 pages/declaration files/Adding to DefinitelyTyped.md diff --git a/pages/declaration files/Adding to DefinitelyTyped.md b/pages/declaration files/Adding to DefinitelyTyped.md deleted file mode 100644 index 146ec1bd5..000000000 --- a/pages/declaration files/Adding to DefinitelyTyped.md +++ /dev/null @@ -1,23 +0,0 @@ -# Creating a New DefinitelyTyped File - -This page will walk you through how to create a new folder in DefinitelyTyped. - -## Create the Folder - -Naming - -## Copy from _template - -## Rename `-tests.ts` - -## Modify tsconfig.json - -Use the template, modify files param, leave remainder untouched - -## Write Your File - -## Test for Compilation - -## Test for Conformance - -## Test for Breaks \ No newline at end of file From 80a7d6edbb5cc67c68ece2fdc7ca7fab423be3d9 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Sun, 3 Jul 2016 23:56:09 -0700 Subject: [PATCH 05/29] Remove old writing declaration files page --- pages/Writing Declaration Files.md | 268 ----------------------------- 1 file changed, 268 deletions(-) delete mode 100644 pages/Writing Declaration Files.md diff --git a/pages/Writing Declaration Files.md b/pages/Writing Declaration Files.md deleted file mode 100644 index 8b478bef0..000000000 --- a/pages/Writing Declaration Files.md +++ /dev/null @@ -1,268 +0,0 @@ -# Introduction - -When using an external JavaScript library, or new host API, you'll need to use a declaration file (.d.ts) to describe the shape of that library. -This guide covers a few high-level concepts specific to writing declaration files, then proceeds with a number of examples that show how to transcribe various concepts to their matching declaration file descriptions. - -# Guidelines and Specifics - -## Workflow - -The best way to write a .d.ts file is to start from the documentation of the library, not the code. -Working from the documentation ensures the surface you present isn't muddied with implementation details, and is typically much easier to read than JS code. -The examples below will be written as if you were reading documentation that presented example calling code. - -## Namespacing - -When defining interfaces (for example, "options" objects), you have a choice about whether to put these types inside a namespace or not. -This is largely a judgement call -- if the consumer is likely to often declare variables or parameters of that type, and the type can be named without risk of colliding with other types, prefer placing it in the global namespace. -If the type is not likely to be referenced directly, or can't be named with a reasonably unique name, do use a namespace to prevent it from colliding with other types. - -## Callbacks - -Many JavaScript libraries take a function as a parameter, then invoke that function later with a known set of arguments. -When writing the function signatures for these types, *do not* mark those parameters as optional. -The right way to think of this is *"What parameters will be provided?"*, not *"What parameters will be consumed?"*. -While TypeScript 0.9.7 and above does not enforce that the optionality, bivariance on argument optionality might be enforced by an external linter. - -## Extensibility and Declaration Merging - -When writing declaration files, it's important to remember TypeScript's rules for extending existing objects. -You might have a choice of declaring a variable using an anonymous type or an interface type: - -#### Anonymously-typed var - -```ts -declare var MyPoint: { x: number; y: number; }; -``` - -#### Interfaced-typed var - -```ts -interface SomePoint { x: number; y: number; } -declare var MyPoint: SomePoint; -``` - -From a consumption side these declarations are identical, but the type `SomePoint` can be extended through interface merging: - -```ts -interface SomePoint { z: number; } -MyPoint.z = 4; // OK -``` - -Whether or not you want your declarations to be extensible in this way is a bit of a judgement call. -As always, try to represent the intent of the library here. - -## Class Decomposition - -Classes in TypeScript create two separate types: the instance type, which defines what members an instance of a class has, and the constructor function type, which defines what members the class constructor function has. -The constructor function type is also known as the "static side" type because it includes static members of the class. - -While you can reference the static side of a class using the `typeof` keyword, it is sometimes useful or necessary when writing declaration files to use the *decomposed class* pattern which explicitly separates the instance and static types of class. - -As an example, the following two declarations are nearly equivalent from a consumption perspective: - -#### Standard - -```ts -class A { - static st: string; - inst: number; - constructor(m: any) {} -} -``` - -#### Decomposed - -```ts -interface A_Static { - new(m: any): A_Instance; - st: string; -} -interface A_Instance { - inst: number; -} -declare var A: A_Static; -``` - -The trade-offs here are as follows: - -* Standard classes can be inherited from using `extends`; decomposed classes cannot. This might change in later version of TypeScript if arbitrary `extends` expressions are allowed. -* It is possible to add members later (through declaration merging) to the static side of both standard and decomposed classes -* It is possible to add instance members to decomposed classes, but not standard classes -* You'll need to come up with sensible names for more types when writing a decomposed class - -## Naming Conventions - -In general, you shouldn't prefix interfaces with `I` (e.g. `IColor`). -Because the concept of an interface in TypeScript is much more broad than in C# or Java, the `IFoo` naming convention is not broadly useful. - -# Examples - -Let's jump in to the examples section. For each example, sample *usage* of the library is provided, followed by the declaration code that accurately types the usage. -When there are multiple good representations, more than one declaration sample might be listed. - -## Options Objects - -#### Usage - -```ts -animalFactory.create("dog"); -animalFactory.create("giraffe", { name: "ronald" }); -animalFactory.create("panda", { name: "bob", height: 400 }); -// Invalid: name must be provided if options is given -animalFactory.create("cat", { height: 32 }); -``` - -#### Typing - -```ts -namespace animalFactory { - interface AnimalOptions { - name: string; - height?: number; - weight?: number; - } - function create(name: string, animalOptions?: AnimalOptions): Animal; -} -``` - -## Functions with Properties - -#### Usage - -```ts -zooKeeper.workSchedule = "morning"; -zooKeeper(giraffeCage); -``` - -#### Typing - -```ts -// Note: Function must precede namespace -function zooKeeper(cage: AnimalCage); -namespace zooKeeper { - var workSchedule: string; -} -``` - -## New + callable methods - -#### Usage - -```ts -var w = widget(32, 16); -var y = new widget("sprocket"); -// w and y are both widgets -w.sprock(); -y.sprock(); -``` - -#### Typing - -```ts -interface Widget { - sprock(): void; -} - -interface WidgetFactory { - new(name: string): Widget; - (width: number, height: number): Widget; -} - -declare var widget: WidgetFactory; -``` - -## Global / External-agnostic Libraries - -These libraries can be used as either globals or imports. -In a module file (one with any imports/exports), using these as globals is not allowed. -These are also known as [UMD](https://github.com/umdjs/umd) modules. - -#### Usage - -```ts -// Either -import x = require("zoo"); -x.open(); -// or -zoo.open(); -``` - -#### Typing - -```ts -export function open(): void; -export as namespace zoo; -``` - -## Single Complex Object in Modules - -#### Usage - -```ts -// Super-chainable library for eagles -import Eagle = require("./eagle"); - -// Call directly -Eagle("bald").fly(); - -// Invoke with new -var eddie = new Eagle("Mille"); - -// Set properties -eddie.kind = "golden"; -``` - -#### Typing - -```ts -interface Eagle { - (kind: string): Eagle; - new (kind: string): Eagle; - - kind: string; - fly(): void -} - -declare var Eagle: Eagle; - -export = Eagle; -``` - -## Function as an Module - -This is a common pattern for modules whose imported entities are callable functions. - -#### Usage - -```ts -import sayHello = require("say-hello"); -sayHello("Travis"); -``` - -#### Typing - -```ts -declare module "say-hello" { - function sayHello(name: string): void; - export = sayHello; -} -``` - -## Callbacks - -#### Usage - -```ts -addLater(3, 4, x => console.log("x = " + x)); -``` - -#### Typing - -```ts -// Note: 'void' return type is preferred here -function addLater(x: number, y: number, callback: (sum: number) => void): void; -``` - -Please post a comment [here](https://github.com/Microsoft/TypeScript-Handbook/issues) if there's a pattern you'd like to see documented! -We'll add to this as we can. From 3c75abc18814197c0b5cf86a8da7bd3e2da34bc2 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 4 Jul 2016 00:13:25 -0700 Subject: [PATCH 06/29] Remove redundant headers --- pages/declaration files/By Example.md | 24 +++++++++---------- pages/declaration files/Do's and Don'ts.md | 22 ++++++++--------- pages/declaration files/Introduction.md | 16 +++++-------- pages/declaration files/Library Structures.md | 2 +- 4 files changed, 28 insertions(+), 36 deletions(-) diff --git a/pages/declaration files/By Example.md b/pages/declaration files/By Example.md index 4dcf4f140..0418c0378 100644 --- a/pages/declaration files/By Example.md +++ b/pages/declaration files/By Example.md @@ -1,6 +1,4 @@ -# Definition Files by Example - -## Introduction +# Introduction The purpose of this guide is to teach you how to write a high-quality definition file. This guide is structured by showing an example *usage* and *documentation*, @@ -15,9 +13,9 @@ These examples are ordered in approximately increasing order of complexity. * [Reusable Types (Global)](#reusable-types-global) * [Classes](#classes) -## The Examples +# The Examples -### Global variables +## Global variables *Documentation* > The global variable `foo` contains the number of widgets present. @@ -38,7 +36,7 @@ You can also use `declare let` if the variable is block-scoped. declare var foo: number; ``` -### Global functions +## Global functions *Documentation* > You can invoke the function `greet` with a string to show a greeting to the user. @@ -57,7 +55,7 @@ Use `declare function` to declare functions. declare function greet(greeting: string): void; ``` -### Objects with Properties +## Objects with Properties *Documentation* > The global variable `myLib` has a function `makeGreeting` for creating greetings, @@ -82,7 +80,7 @@ declare namespace myLib { } ``` -### Overloaded functions +## Overloaded functions *Documentation* > The `getWidget` function accepts a number and return a Widget, or accepts a string and returns a Widget array @@ -101,7 +99,7 @@ declare function getWidget(n: number): Widget; declare function getWidget(s: string): Widget[]; ``` -### Reusable Types (interfaces) +## Reusable Types (interfaces) *Documentation* > When specifying a greeting, you must pass a GreetingSettings object. @@ -132,7 +130,7 @@ interface GreetingSettings { declare function greet(setting: GreetingSettings): void; ``` -### Reusable Types (type aliases) +## Reusable Types (type aliases) *Documentation* > Anywhere a greeting is expected, you can provide a `string`, @@ -161,7 +159,7 @@ type GreetingLike = string | (() => string) | Greeting; declare function greet(g: GreetingLike): void; ``` -### Organizing Types +## Organizing Types *Documentation* > The `greeter` object can log to a file, or display an alert. @@ -208,7 +206,7 @@ declare namespace GreetingLib.Options { } ``` -### Classes +## Classes *Documentation* > You can create a greeter by instantiating the `Greeter` object, @@ -243,7 +241,7 @@ declare class Greeter { -## Callback Types +# Callback Types -### Return Types of Callbacks +## Return Types of Callbacks @@ -63,7 +61,7 @@ function fn(x: () => void) { } ``` -### Optional Parameters in Callbacks +## Optional Parameters in Callbacks *Don't* use optional parameters in callbacks unless you really mean it: @@ -88,7 +86,7 @@ interface Fetcher { } ``` -### Overloads and Callbacks +## Overloads and Callbacks *Don't* write separate overloads that differ only on callback arity: @@ -108,9 +106,9 @@ declare function beforeAll(action: (done: DoneFn) => void, timeout?: number): vo *Why*: It's always legal for a callback to disregard a parameter, so there's no need for the shorter overload. Providing a shorter callback first allows incorrectly-typed functions to be passed in because they match the first overload. -## Function Overloads +# Function Overloads -### Ordering +## Ordering *Don't* put more general overloads before more specific overloads: @@ -139,7 +137,7 @@ var x = fn(myElem); // x: string, :) *Why*: TypeScript chooses the *first matching overload* when resolving function calls. When an earlier overload is "more general" than a later one, the later one is effectively hidden and cannot be called. -### Use Optional Parameters +## Use Optional Parameters *Don't* write several overloads that differ only in trailing parameters: @@ -188,7 +186,7 @@ var x: Moment; x.diff(something, someOtherThing ? undefined : "hour"); ``` -### Use Union Types +## Use Union Types *Don't* write overloads that differ by type in only one argument position: diff --git a/pages/declaration files/Introduction.md b/pages/declaration files/Introduction.md index df6dcd1de..cf742f873 100644 --- a/pages/declaration files/Introduction.md +++ b/pages/declaration files/Introduction.md @@ -1,24 +1,20 @@ -# .d.ts File Writing: A Complete Guide - -## Introduction - This guide is designed to teach you how to write a high-quality TypeScript Declaration File. In this guide, we'll 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. -## Sections +# Sections The guide is broken down into the following sections. -### Library Structures +## Library Structures The [Library Structures](./Library Structures.md) guide helps you understand common library formats and how to write a correct declaration file for each formats. If you're editing an existing file, you probably don't need to read this section. Authors of new declaration files must read this section to properly understand how the format of the library influences the writing of the declaration file. -### Do's and Don'ts +## Do's and Don'ts Many common mistakes in declaration files can be easily avoided. The [Do's and Don'ts](./Do's and Don'ts.md) section identifies common errors, @@ -26,19 +22,19 @@ The [Do's and Don'ts](./Do's and Don'ts.md) section identifies common errors, and how to fix them. Everyone should read this section to help themselves avoid common mistakes. -### By Example +## By Example Many times, we are faced with writing a declaration file when we only have examples of the underlying library to guide us. The [By Example](./By Example.md) 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. -### Deep Dive +## Deep Dive For seasoned authors interested in the underlying mechanics of how declaration files work, the [Deep Dive](./Deep Dive.md) section explains many advanced concepts in declaration writing, and shows how to leverage these concepts to create cleaner and more intuitive declaration files. -### `/templates` +## `/templates` In the `templates` directory, you'll find a number of declaration files that serve as a useful starting point when writing a new file. diff --git a/pages/declaration files/Library Structures.md b/pages/declaration files/Library Structures.md index b51425004..77839c463 100644 --- a/pages/declaration files/Library Structures.md +++ b/pages/declaration files/Library Structures.md @@ -1,4 +1,4 @@ -# Structuring: Overview +# Overview Broadly speaking, the way you *structure* your definition file depends on how the library is consumed. There are many ways of offering a library for consumption in JavaScript, From 8ca34972fe39508257966e299d6f4d73c66d4603 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 4 Jul 2016 10:23:55 -0700 Subject: [PATCH 07/29] Fix links --- pages/declaration files/By Example.md | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/pages/declaration files/By Example.md b/pages/declaration files/By Example.md index 0418c0378..96328f146 100644 --- a/pages/declaration files/By Example.md +++ b/pages/declaration files/By Example.md @@ -6,16 +6,18 @@ This guide is structured by showing an example *usage* and *documentation*, These examples are ordered in approximately increasing order of complexity. -* [Global variable](#global-variable) -* [Global function](#global-function) -* [Object with Properties](#object-with-properties) -* [Overloaded function](#overloaded-function) -* [Reusable Types (Global)](#reusable-types-global) +* [Global Variables](#global-variables) +* [Global Functions](#global-functions) +* [Objects with Properties](#objects-with-properties) +* [Overloaded Function](#overloaded-functions) +* [Reusable Types (Interfaces)](#reusable-types-interfaces) +* [Reusable Types (Type Aliases)](#reusable-types-type-aliases) +* [Organizing Types)](#organizing-types) * [Classes](#classes) # The Examples -## Global variables +## Global Variables *Documentation* > The global variable `foo` contains the number of widgets present. @@ -36,7 +38,7 @@ You can also use `declare let` if the variable is block-scoped. declare var foo: number; ``` -## Global functions +## Global Functions *Documentation* > You can invoke the function `greet` with a string to show a greeting to the user. @@ -80,7 +82,7 @@ declare namespace myLib { } ``` -## Overloaded functions +## Overloaded Functions *Documentation* > The `getWidget` function accepts a number and return a Widget, or accepts a string and returns a Widget array @@ -99,7 +101,7 @@ declare function getWidget(n: number): Widget; declare function getWidget(s: string): Widget[]; ``` -## Reusable Types (interfaces) +## Reusable Types (Interfaces) *Documentation* > When specifying a greeting, you must pass a GreetingSettings object. @@ -130,7 +132,7 @@ interface GreetingSettings { declare function greet(setting: GreetingSettings): void; ``` -## Reusable Types (type aliases) +## Reusable Types (Type Aliases) *Documentation* > Anywhere a greeting is expected, you can provide a `string`, From 04f99c3bc2786d6a05d487e3371ba6add18b0956 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 4 Jul 2016 12:23:08 -0700 Subject: [PATCH 08/29] Add publishing section --- pages/declaration files/Introduction.md | 4 ++ pages/declaration files/Publishing.md | 94 +++++++++++++++++++++++++ 2 files changed, 98 insertions(+) create mode 100644 pages/declaration files/Publishing.md diff --git a/pages/declaration files/Introduction.md b/pages/declaration files/Introduction.md index cf742f873..fcdb158ad 100644 --- a/pages/declaration files/Introduction.md +++ b/pages/declaration files/Introduction.md @@ -39,3 +39,7 @@ For seasoned authors interested in the underlying mechanics of how declaration f In the `templates` directory, 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](./Library Structures.md) to figure out which template file to use. + +## Publish to npm + +The [Publishing](./Publishing.md) section explains how to publish your declaration files to an npm package, and shows how to manage your dependent packages. diff --git a/pages/declaration files/Publishing.md b/pages/declaration files/Publishing.md new file mode 100644 index 000000000..43de360d2 --- /dev/null +++ b/pages/declaration files/Publishing.md @@ -0,0 +1,94 @@ +Now that you have authored a declartion file following the steps of this guid, it is time to publish it to npm. +There are two main ways you can publish your declaration files to npm: 1. bundeling with your npm package, or 2. publishing to [@types organization](https://www.npmjs.com/~types) on npm. + +If you control the npm package you are publishing declations for, then the first approch is favoured; this way your declarations and javascript always travel togather. + +# Bundel with npm package + +You will need to indicate the main declaration file for your `package.json` file, similar to how you indicate the main `.js` file. +Set the `types` property to point to your bundled declaration file. +For example: + +```json +{ + "name": "awesome", + "author": "Vandelay Industries", + "version": "1.0.0", + "main": "./lib/main.js", + "types": "./lib/main.d.ts" +} +``` + +Note that `"typings"` is another synonum for `"types"` and can be used as well. + +Also note that if your main declaration file is named `index.d.ts` and lives at the root of the package (next to `index.js`) you do not need to mark the `"types"` property, though it is advisable to do so. + +## Dependencies + +All depenencies are managed by npm. +Make sure all the declaration packages you depend on are marked appropriatelly in the `"dependnecies"` section in your `package.json`. +For example: + +```json +{ + "name": "browserify-typescript-extension", + "author": "Vandelay Industries", + "version": "1.0.0", + "main": "./lib/main.js", + "types": "./lib/main.d.ts" + "dependnecies" : [ + "browserify": "latest", + "@types/browserify": "latest", + "typescript": "next" + ] +} +``` + +In this example this package depends on `browserify`, and `typescript`. +It does expose declarations that uses the declarations in these packages; so any user or our `browserify-typescript-extension` package needs to have these depenencies as well. + +`browserify` does not bundle its declaration files with its npm packages, thus the declaration files come from `@types/browserify`. +`typescript` however, bundles its declaration files, so no need to add additonal references. + +Note that you need to use `"dependnecies"` and not `"devDependencies"` since your declarations depend on these dependnecies. + +## Red flags + +### `/// + +*Don't* use `/// ` in your declaration files. + +```ts +/// +.... +``` + +*Do* use `/// ` instead. + +```ts +/// +.... +``` + +Make sure to revisit the [Consuming dependencies](./Library Structures.md#consuming-dependencies) section for more infromation. + +### Bundling dependent declarations + +If your type definitions depend on another package: + +* *Don't* combine it with yours, keep each in their own file. +* *Don't* copy the declarations in your package either. +* *Do* depend on the npm type declaration package. + +## Publicize your declaration file + +After publishing your declaration file with your package, make sure to add a reference to it in the [DefinitelyTyped repo external package list](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/types-2.0/notNeededPackages.json). +Adding this will allow search tool to know that your package provides its own declarations. + +TODO: more about this. + +# Publish to [@types](https://www.npmjs.com/~types) + +Packages on under the [@types](https://www.npmjs.com/~types) organization are published automatically from [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped) using the [types-publisher tool](https://github.com/Microsoft/types-publisher). +To get your declarations publised as an @types package, please submit a pull request to [https://github.com/DefinitelyTyped/DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped). +You can find more details in the [conribution guidlines page](http://definitelytyped.org/guides/contributing.html). \ No newline at end of file From 83353e20cd219b20f36cf8c18a5d608bcbdeea39 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 4 Jul 2016 12:44:59 -0700 Subject: [PATCH 09/29] fix typos --- pages/declaration files/Publishing.md | 28 +++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/pages/declaration files/Publishing.md b/pages/declaration files/Publishing.md index 43de360d2..18d6c4e73 100644 --- a/pages/declaration files/Publishing.md +++ b/pages/declaration files/Publishing.md @@ -1,9 +1,9 @@ -Now that you have authored a declartion file following the steps of this guid, it is time to publish it to npm. -There are two main ways you can publish your declaration files to npm: 1. bundeling with your npm package, or 2. publishing to [@types organization](https://www.npmjs.com/~types) on npm. +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 2. publishing to [@types organization](https://www.npmjs.com/~types) on npm. -If you control the npm package you are publishing declations for, then the first approch is favoured; this way your declarations and javascript always travel togather. +If you control the npm package you are publishing declarations for, then the first approach is favored; this way your declarations and JavaScript always travel together. -# Bundel with npm package +# Bundle with npm package You will need to indicate the main declaration file for your `package.json` file, similar to how you indicate the main `.js` file. Set the `types` property to point to your bundled declaration file. @@ -19,14 +19,14 @@ For example: } ``` -Note that `"typings"` is another synonum for `"types"` and can be used as well. +Note that `"typings"` is synonymous with `"types"` and can be used as well. Also note that if your main declaration file is named `index.d.ts` and lives at the root of the package (next to `index.js`) you do not need to mark the `"types"` property, though it is advisable to do so. ## Dependencies -All depenencies are managed by npm. -Make sure all the declaration packages you depend on are marked appropriatelly in the `"dependnecies"` section in your `package.json`. +All dependencies are managed by npm. +Make sure all the declaration packages you depend on are marked appropriately in the `"dependencies"` section in your `package.json`. For example: ```json @@ -36,7 +36,7 @@ For example: "version": "1.0.0", "main": "./lib/main.js", "types": "./lib/main.d.ts" - "dependnecies" : [ + "dependencies" : [ "browserify": "latest", "@types/browserify": "latest", "typescript": "next" @@ -45,12 +45,12 @@ For example: ``` In this example this package depends on `browserify`, and `typescript`. -It does expose declarations that uses the declarations in these packages; so any user or our `browserify-typescript-extension` package needs to have these depenencies as well. +It does expose declarations that uses the declarations in these packages; so any user or our `browserify-typescript-extension` package needs to have these dependencies as well. `browserify` does not bundle its declaration files with its npm packages, thus the declaration files come from `@types/browserify`. -`typescript` however, bundles its declaration files, so no need to add additonal references. +`typescript` however, bundles its declaration files, so no need to add additional references. -Note that you need to use `"dependnecies"` and not `"devDependencies"` since your declarations depend on these dependnecies. +Note that you need to use `"dependencies"` and not `"devDependencies"` since your declarations depend on these dependencies. ## Red flags @@ -70,7 +70,7 @@ Note that you need to use `"dependnecies"` and not `"devDependencies"` since you .... ``` -Make sure to revisit the [Consuming dependencies](./Library Structures.md#consuming-dependencies) section for more infromation. +Make sure to revisit the [Consuming dependencies](./Library Structures.md#consuming-dependencies) section for more information. ### Bundling dependent declarations @@ -90,5 +90,5 @@ TODO: more about this. # Publish to [@types](https://www.npmjs.com/~types) Packages on under the [@types](https://www.npmjs.com/~types) organization are published automatically from [DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped) using the [types-publisher tool](https://github.com/Microsoft/types-publisher). -To get your declarations publised as an @types package, please submit a pull request to [https://github.com/DefinitelyTyped/DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped). -You can find more details in the [conribution guidlines page](http://definitelytyped.org/guides/contributing.html). \ No newline at end of file +To get your declarations published as an @types package, please submit a pull request to [https://github.com/DefinitelyTyped/DefinitelyTyped](https://github.com/DefinitelyTyped/DefinitelyTyped). +You can find more details in the [contribution guidelines page](http://definitelytyped.org/guides/contributing.html). \ No newline at end of file From 84b218f03a91a5a0c5734224de51fb06a85b72b9 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 4 Jul 2016 12:45:11 -0700 Subject: [PATCH 10/29] Add a consumption section --- pages/declaration files/Consumption.md | 32 +++++++++++++++++++++++++ pages/declaration files/Introduction.md | 4 ++++ 2 files changed, 36 insertions(+) create mode 100644 pages/declaration files/Consumption.md diff --git a/pages/declaration files/Consumption.md b/pages/declaration files/Consumption.md new file mode 100644 index 000000000..6814c96ee --- /dev/null +++ b/pages/declaration files/Consumption.md @@ -0,0 +1,32 @@ +# 1. Search + +Check out [https://aka.ms/types](https://aka.ms/types) to find the package for your favorite library. + +> Note: if the declaration file you are searching for is not present, you can always contribute one back and help out the next developer looking for it. +> Please see the DefinitelyTyped [contribution guidelines page](http://definitelytyped.org/guides/contributing.html) for details. + +# 2. Download + +Getting type declarations in TypeScript 2.0 require no tools apart from npm. + +As an example, getting the declarations for a library like lodash will be just an npm command away: + +```cmd +npm install --save-dev @types/lodash +``` + +From there you’ll be able to use lodash in your TypeScript code with no fuss. +This works for both modules and global code. + +For example, once you’ve npm install-ed your type declarations, then you can use imports and write + +```ts +import * as _ from "lodash"; +_.padStart("Hello TypeScript!", 20, " "); +``` + +or if you’re not using modules, you can just use the global variable `_` if you have a `tsconfig.json` around. + +```ts +_.padStart("Hello TypeScript!", 20, " "); +``` \ No newline at end of file diff --git a/pages/declaration files/Introduction.md b/pages/declaration files/Introduction.md index fcdb158ad..96b15db35 100644 --- a/pages/declaration files/Introduction.md +++ b/pages/declaration files/Introduction.md @@ -43,3 +43,7 @@ Refer to the documentation in [Library Structures](./Library Structures.md) to f ## Publish to npm The [Publishing](./Publishing.md) section explains how to publish your declaration files to an npm package, and shows how to manage your dependent packages. + +## Finding and Installing Declaration Files + +For JavaScrit library users, the [Finding and Installing Declaration Files](./Consumption.md) section offers two simple steps to locate and install corresponding declaration files. From 16ea13b8c73f4fc3d2ef4b2e50f09bd2840fa49f Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 4 Jul 2016 12:46:56 -0700 Subject: [PATCH 11/29] Update title --- pages/declaration files/Introduction.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pages/declaration files/Introduction.md b/pages/declaration files/Introduction.md index 96b15db35..28565ba7f 100644 --- a/pages/declaration files/Introduction.md +++ b/pages/declaration files/Introduction.md @@ -44,6 +44,6 @@ Refer to the documentation in [Library Structures](./Library Structures.md) to f The [Publishing](./Publishing.md) section explains how to publish your declaration files to an npm package, and shows how to manage your dependent packages. -## Finding and Installing Declaration Files +## Find and Install Declaration Files -For JavaScrit library users, the [Finding and Installing Declaration Files](./Consumption.md) section offers two simple steps to locate and install corresponding declaration files. +For JavaScrit library users, the [Find and Install Declaration Files](./Consumption.md) section offers two simple steps to locate and install corresponding declaration files. From b23581083e6470e4ca92795237e4bc1609ab479b Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Mon, 4 Jul 2016 12:48:58 -0700 Subject: [PATCH 12/29] Add redirect notice --- pages/Typings for NPM Packages.md | 29 +---------------------------- 1 file changed, 1 insertion(+), 28 deletions(-) diff --git a/pages/Typings for NPM Packages.md b/pages/Typings for NPM Packages.md index 7517336f0..8c63d4ce5 100644 --- a/pages/Typings for NPM Packages.md +++ b/pages/Typings for NPM Packages.md @@ -1,28 +1 @@ -The TypeScript compiler resolves Node module names by following the [Node.js module resolution algorithm](https://nodejs.org/api/modules.html#modules_all_together). -TypeScript can also load typings that are bundled with npm packages. -The compiler will try to discover typings for module `"foo"` using the following set of rules: - -1. Try to load the `package.json` file located in the appropriate package folder (`node_modules/foo/`). If present,read the path to the typings file described in the `"typings"` field. For example, in the following `package.json`, the compiler will resolve the typings at `node_modules/foo/lib/foo.d.ts` - - ```json - { - "name": "foo", - "author": "Vandelay Industries", - "version": "1.0.0", - "main": "./lib/foo.js", - "typings": "./lib/foo.d.ts" - } - ``` - -2. Try to load a file named `index.d.ts` located in the package folder (`node_modules/foo/`) - this file should contain typings for the package. - -The precise algorithm for module resolution can be found [here](https://github.com/Microsoft/TypeScript/issues/2338). - -### Your definition files should - -* be`.d.ts` files -* be written as external modules -* not contain triple-slash references - -The rationale is that typings should not bring new compilable items to the set of compiled files; otherwise actual implementation files in the package can be overwritten during compilation. -Additionally, **loading typings should not pollute global scope** by bringing potentially conflicting entries from different version of the same library. \ No newline at end of file +> ## This page moved to [Publishing](./declaration files/Publishing.md). \ No newline at end of file From a7dc1b4adf11094cf2df749c8e410a3505e490a3 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 5 Jul 2016 09:34:57 -0700 Subject: [PATCH 13/29] Fix lint issues --- pages/Typings for NPM Packages.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/Typings for NPM Packages.md b/pages/Typings for NPM Packages.md index 8c63d4ce5..e991e9e43 100644 --- a/pages/Typings for NPM Packages.md +++ b/pages/Typings for NPM Packages.md @@ -1 +1 @@ -> ## This page moved to [Publishing](./declaration files/Publishing.md). \ No newline at end of file +> ## This page moved to [Publishing](./declaration files/Publishing.md) \ No newline at end of file From 53c0b4e38f56337ae224be04300b1da435830ac0 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 5 Jul 2016 10:27:43 -0700 Subject: [PATCH 14/29] Remove extra paren --- pages/declaration files/By Example.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/declaration files/By Example.md b/pages/declaration files/By Example.md index 96328f146..8203e89f5 100644 --- a/pages/declaration files/By Example.md +++ b/pages/declaration files/By Example.md @@ -12,7 +12,7 @@ These examples are ordered in approximately increasing order of complexity. * [Overloaded Function](#overloaded-functions) * [Reusable Types (Interfaces)](#reusable-types-interfaces) * [Reusable Types (Type Aliases)](#reusable-types-type-aliases) -* [Organizing Types)](#organizing-types) +* [Organizing Types](#organizing-types) * [Classes](#classes) # The Examples From 0751425b938ebd2567cf47bf4e41ab7f810b40f6 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 5 Jul 2016 11:54:20 -0700 Subject: [PATCH 15/29] Update links --- pages/declaration files/Introduction.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pages/declaration files/Introduction.md b/pages/declaration files/Introduction.md index 28565ba7f..59af344d8 100644 --- a/pages/declaration files/Introduction.md +++ b/pages/declaration files/Introduction.md @@ -36,7 +36,7 @@ For seasoned authors interested in the underlying mechanics of how declaration f ## `/templates` -In the `templates` directory, you'll find a number of declaration files that serve as a useful starting point +In the [`templates`](./templates) directory, 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](./Library Structures.md) to figure out which template file to use. @@ -46,4 +46,4 @@ The [Publishing](./Publishing.md) section explains how to publish your declarati ## Find and Install Declaration Files -For JavaScrit library users, the [Find and Install Declaration Files](./Consumption.md) section offers two simple steps to locate and install corresponding declaration files. +For JavaScrit library users, the [Consumption](./Consumption.md) section offers two simple steps to locate and install corresponding declaration files. From 8242822f8dd6e85e5bbb0bf376f09cedc20e660e Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 5 Jul 2016 15:28:44 -0700 Subject: [PATCH 16/29] hide todo comments --- pages/declaration files/Deep Dive.md | 2 +- pages/declaration files/Publishing.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pages/declaration files/Deep Dive.md b/pages/declaration files/Deep Dive.md index e92e6a530..2ac05fdf3 100644 --- a/pages/declaration files/Deep Dive.md +++ b/pages/declaration files/Deep Dive.md @@ -228,4 +228,4 @@ The second block creates the following name meanings: An important rule is that `export` and `import` declarations export or import *all meanings* of their targets. -TODO: Write more on that. + diff --git a/pages/declaration files/Publishing.md b/pages/declaration files/Publishing.md index 18d6c4e73..6c8888c89 100644 --- a/pages/declaration files/Publishing.md +++ b/pages/declaration files/Publishing.md @@ -85,7 +85,7 @@ If your type definitions depend on another package: After publishing your declaration file with your package, make sure to add a reference to it in the [DefinitelyTyped repo external package list](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/types-2.0/notNeededPackages.json). Adding this will allow search tool to know that your package provides its own declarations. -TODO: more about this. + # Publish to [@types](https://www.npmjs.com/~types) From 9bad0a6b4839b764ba1b5e6974d2792a60cb5dd2 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 5 Jul 2016 15:30:07 -0700 Subject: [PATCH 17/29] Add redirect --- pages/Writing Declaration Files.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 pages/Writing Declaration Files.md diff --git a/pages/Writing Declaration Files.md b/pages/Writing Declaration Files.md new file mode 100644 index 000000000..56ba20ab9 --- /dev/null +++ b/pages/Writing Declaration Files.md @@ -0,0 +1 @@ +> ## This page moved to [Publishing](./declaration files/Introduction.md) \ No newline at end of file From d0e9948a41050db05bf9addbb1b84c55b79a4ed2 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 5 Jul 2016 15:40:58 -0700 Subject: [PATCH 18/29] Fix links --- pages/declaration files/Library Structures.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pages/declaration files/Library Structures.md b/pages/declaration files/Library Structures.md index 77839c463..d57401aeb 100644 --- a/pages/declaration files/Library Structures.md +++ b/pages/declaration files/Library Structures.md @@ -82,7 +82,7 @@ However, libraries that are small and require the DOM (or have *no* dependencies ### Template The template file [`global.d.ts`](./templates/global.d.ts) defines an example library `myLib`. -Be sure to read the "Preventing Name Conflicts" footnote. +Be sure to read the ["Preventing Name Conflicts" footnote](#preventing-name-conflicts). ## *module* @@ -196,7 +196,7 @@ var x = require('foo'); var y = x(42); ``` -Be sure to read the footnote ["The Impact of ES6 on Module Call Signatures"](#) +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`](./templates/module-class.d.ts) if your module can be *constructed* using `new`: @@ -206,7 +206,7 @@ var x = require('bar'); var y = new x('hello'); ``` -The same footnote applies to these modules. +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`](./templates/module.d.ts) file. From 4170c488a7bfa2d91b48c4413a12fe309b8c0146 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 5 Jul 2016 15:42:25 -0700 Subject: [PATCH 19/29] Update By Example.md --- pages/declaration files/By Example.md | 66 ++++++++++++++++----------- 1 file changed, 39 insertions(+), 27 deletions(-) diff --git a/pages/declaration files/By Example.md b/pages/declaration files/By Example.md index 8203e89f5..4d3747f44 100644 --- a/pages/declaration files/By Example.md +++ b/pages/declaration files/By Example.md @@ -1,7 +1,7 @@ # Introduction The purpose of this guide is to teach you how to write a high-quality definition file. -This guide is structured by showing an example *usage* and *documentation*, +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. @@ -20,15 +20,17 @@ These examples are ordered in approximately increasing order of complexity. ## 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)); +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. @@ -41,12 +43,13 @@ declare var foo: number; ## Global Functions *Documentation* -> You can invoke the function `greet` with a string to show a greeting to the user. + +> You can call the function `greet` with a string to show a greeting to the user. *Code* ```ts -greet('hello, world'); +greet("hello, world"); ``` *Declaration* @@ -60,15 +63,17 @@ declare function greet(greeting: string): void; ## Objects with Properties *Documentation* + > The global variable `myLib` has a function `makeGreeting` for creating greetings, -> and a property `numberOfGreetings` indicating the number of greetings made so far. +> and a property `numberOfGreetings` indicating the number of greetings made so far. *Code* ```ts -var result = myLib.makeGreeting('hello, world'); -console.log('The computed greeting is:' + result); -var count = myLib.numberOfGreetings; +let result = myLib.makeGreeting("hello, world"); +console.log("The computed greeting is:" + result); + +let count = myLib.numberOfGreetings; ``` *Declaration* @@ -78,6 +83,7 @@ Use `declare namespace` to describe types or values accessed by dotted notation. ```ts declare namespace myLib { function makeGreeting(s: string): string; + let numberOfGreetings: number; } ``` @@ -85,13 +91,15 @@ declare namespace myLib { ## Overloaded Functions *Documentation* -> The `getWidget` function accepts a number and return a Widget, or accepts a string and returns a Widget array + +The `getWidget` function accepts a number and returns a Widget, or accepts a string and returns a Widget array. *Code* ```ts let x: Widget = getWidget(43); -let arr = getWidget('all of them'); // arr: Widget[] + +let arr: Widget[] = getWidget("all of them"); ``` *Declaration* @@ -104,7 +112,8 @@ declare function getWidget(s: string): Widget[]; ## Reusable Types (Interfaces) *Documentation* -> When specifying a greeting, you must pass a GreetingSettings object. + +> When specifying a greeting, you must pass a `GreetingSettings` object. > This object has the following properties: > - greeting: Mandatory string > - duration: Optional length of time (in milliseconds) @@ -114,14 +123,14 @@ declare function getWidget(s: string): Widget[]; ```ts greet({ - greeting: 'hello world', + greeting: "hello world", duration: 4000 }); ``` *Declaration* -Use `interface` to define a type with properties. +Use an `interface` to define a type with properties. ```ts interface GreetingSettings { @@ -129,24 +138,25 @@ interface GreetingSettings { duration?: number; color?: string; } + declare function greet(setting: GreetingSettings): void; ``` ## Reusable Types (Type Aliases) *Documentation* -> Anywhere a greeting is expected, you can provide a `string`, -> a function returning a `string`, or a `Greeter` class. + +> Anywhere a greeting is expected, you can provide a `string`, a function returning a `string`, or a `Greeter` instance. *Code* ```ts function getGreeting() { - return 'howdy'; + return "howdy"; } class MyGreeter extends Greeter { } -greet('hello'); +greet("hello"); greet(getGreeting); greet(new MyGreeter()); ``` @@ -164,15 +174,16 @@ declare function greet(g: GreetingLike): void; ## Organizing Types *Documentation* -> The `greeter` object can log to a file, or display an alert. -> You can provide LogOptions to `.log(...)` or alert options to `.alert(...)` + +> The `greeter` object can log to a file or display an alert. +> You can provide LogOptions to `.log(...)` and alert options to `.alert(...)` *Code* ```ts -const g = new Greeter('Hello'); +const g = new Greeter("Hello"); g.log({ verbose: true }); -g.alert({ modal: false, title: 'Current Greeting' }); +g.alert({ modal: false, title: "Current Greeting" }); ``` *Declaration* @@ -211,25 +222,26 @@ declare namespace GreetingLib.Options { ## Classes *Documentation* -> You can create a greeter by instantiating the `Greeter` object, -> or create a customized greeter by extending from it. + +> You can create a greeter by instantiating the `Greeter` object, or create a customized greeter by extending from it. *Code* ```ts -const myGreeter = new Greeter('hello, world'); -myGreeter.greeting = 'howdy'; +const myGreeter = new Greeter("hello, world"); +myGreeter.greeting = "howdy"; myGreeter.showGreeting(); class SpecialGreeter extends Greeter { constructor() { - super('Very special greetings'); + super("Very special greetings"); } } ``` *Declaration* -Use `declare class` to describe a class or classlike object. + +Use `declare class` to describe a class or class-like object. Classes can have properties and methods as well as a constructor. ```ts From 30897039fd20eda406d8775d5ae61af987aa0ea6 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 5 Jul 2016 15:51:38 -0700 Subject: [PATCH 20/29] Update Consumption.md --- pages/declaration files/Consumption.md | 32 +++++++++++++++----------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/pages/declaration files/Consumption.md b/pages/declaration files/Consumption.md index 6814c96ee..279d7ae85 100644 --- a/pages/declaration files/Consumption.md +++ b/pages/declaration files/Consumption.md @@ -1,32 +1,38 @@ -# 1. Search +In TypeScript 2.0, it has become significantly easier to consume declaration files, in acquiring, using, and finding them. +This page details exactly how to do all three -Check out [https://aka.ms/types](https://aka.ms/types) to find the package for your favorite library. +# Downloading -> Note: if the declaration file you are searching for is not present, you can always contribute one back and help out the next developer looking for it. -> Please see the DefinitelyTyped [contribution guidelines page](http://definitelytyped.org/guides/contributing.html) for details. - -# 2. Download +Getting type declarations in TypeScript 2.0 and above requires no tools apart from npm. -Getting type declarations in TypeScript 2.0 require no tools apart from npm. - -As an example, getting the declarations for a library like lodash will be just an npm command away: +As an example, getting the declarations for a library like lodash takes nothing more than the following command ```cmd -npm install --save-dev @types/lodash +npm install --save @types/lodash ``` +# Consuming + From there you’ll be able to use lodash in your TypeScript code with no fuss. This works for both modules and global code. -For example, once you’ve npm install-ed your type declarations, then you can use imports and write +For example, once you’ve `npm install`-ed your type declarations, you can use imports and write ```ts import * as _ from "lodash"; _.padStart("Hello TypeScript!", 20, " "); ``` -or if you’re not using modules, you can just use the global variable `_` if you have a `tsconfig.json` around. +or if you’re not using modules, you can just use the global variable `_`. ```ts _.padStart("Hello TypeScript!", 20, " "); -``` \ No newline at end of file +``` + +# Searching + +For the most part, type declaration packages should always have the same name as the package name on `npm`, but prefixed with `@types/`, + but if you need, you can check out [https://aka.ms/types](https://aka.ms/types) to find the package for your favorite library. + +> Note: if the declaration file you are searching for is not present, you can always contribute one back and help out the next developer looking for it. +> Please see the DefinitelyTyped [contribution guidelines page](http://definitelytyped.org/guides/contributing.html) for details. From 842c5663a0a47bf97ec63788b82fbc3f906b827c Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 5 Jul 2016 16:07:09 -0700 Subject: [PATCH 21/29] Update Introduction.md --- pages/declaration files/Introduction.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pages/declaration files/Introduction.md b/pages/declaration files/Introduction.md index 59af344d8..db9563d10 100644 --- a/pages/declaration files/Introduction.md +++ b/pages/declaration files/Introduction.md @@ -10,11 +10,11 @@ The guide is broken down into the following sections. ## Library Structures -The [Library Structures](./Library Structures.md) guide helps you understand common library formats and how to write a correct declaration file for each formats. +The [Library Structures](./Library Structures.md) guide helps you understand common library formats and how to write a correct 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 must read this section to properly understand how the format of the library influences the writing of the declaration file. -## Do's and Don'ts +## "Do"s and "Don't"s Many common mistakes in declaration files can be easily avoided. The [Do's and Don'ts](./Do's and Don'ts.md) section identifies common errors, @@ -46,4 +46,4 @@ The [Publishing](./Publishing.md) section explains how to publish your declarati ## Find and Install Declaration Files -For JavaScrit library users, the [Consumption](./Consumption.md) section offers two simple steps to locate and install corresponding declaration files. +For JavaScript library users, the [Consumption](./Consumption.md) section offers a few simple steps to locate and install corresponding declaration files. From adc00a265815bc0b2ae6c076070c01a1abba9a90 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 5 Jul 2016 16:13:27 -0700 Subject: [PATCH 22/29] Remove folder link --- pages/declaration files/Introduction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/declaration files/Introduction.md b/pages/declaration files/Introduction.md index db9563d10..de3cc423d 100644 --- a/pages/declaration files/Introduction.md +++ b/pages/declaration files/Introduction.md @@ -36,7 +36,7 @@ For seasoned authors interested in the underlying mechanics of how declaration f ## `/templates` -In the [`templates`](./templates) directory, you'll find a number of declaration files that serve as a useful starting point +In the `templates` directory, 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](./Library Structures.md) to figure out which template file to use. From 646e50bcde67afb458fc5d92eafb1033fcb147d2 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 5 Jul 2016 17:52:01 -0700 Subject: [PATCH 23/29] Update Library Structures.md --- pages/declaration files/Library Structures.md | 150 ++++++++---------- 1 file changed, 66 insertions(+), 84 deletions(-) diff --git a/pages/declaration files/Library Structures.md b/pages/declaration files/Library Structures.md index d57401aeb..414e97fa5 100644 --- a/pages/declaration files/Library Structures.md +++ b/pages/declaration files/Library Structures.md @@ -1,27 +1,23 @@ # Overview -Broadly speaking, the way you *structure* your definition 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 definition file to match it. -This guide covers how to identify common library patterns, - and how to write definition files which correspond to that pattern. +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. Each type of major library structuring pattern has a corresponding file in the [`templates`](./templates) directory. You can start with these templates to help you get going faster. # Identifying Kinds of Libraries -First, we'll review the kinds of libraries TypeScript definition files can represent. -We'll briefly show how each kind of library is *used*, - how it is *written*, - and list some example libraries from the real world. +First, we'll review the kinds of libraries TypeScript declaration files can represent. +We'll briefly show how each kind of library is *used*, how it is *written*, and list some example libraries from the real world. -Identifying the structure of a library is the first step in writing its definition file. +Identifying the structure of a library is the first step in writing its declaration file. We'll give hints on how to identify structure both based on its *usage* and its *code*. Depending on the library's documentation and organization, one might be easier than the other. We recommend using whichever is more comfortable to you. -## *global* +## Global Libraries A *global* library is one that can be accessed from the global scope (i.e. without using any form of `import`). Many libraries simply expose one or more global variables for use. @@ -31,15 +27,15 @@ For example, if you were using [jQuery](https://jquery.com/), the `$` variable c $(() => { console.log('hello!'); } ); ``` -You'll usually see guidance in the documentation of a global library of how to use the library in a script tag: +You'll usually see guidance in the documentation of a global library of how to use the library in an HTML script tag: ```html - + ``` 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 definition file, make sure the library isn't actually UMD. +Before writing a global declaration file, make sure the library isn't actually UMD. ### Identifying a Global Library from Code @@ -48,7 +44,7 @@ A global "Hello, world" library might look like this: ```js function createGreeting(s) { - return 'Hello, ' + s; + return "Hello, " + s; } ``` @@ -56,7 +52,7 @@ or like this: ```js window.createGreeting = function(s) { - return 'Hello, ' + s; + return "Hello, " + s; } ``` @@ -69,41 +65,39 @@ When looking at the code of a global library, you'll usually see: You *won't* see: * Checks for, or usage of, module loaders like `require` or `define` -* CommonJS/nodejs-style imports of the form `var fs = require('fs');` +* CommonJS/Node.js-style imports of the form `var fs = require("fs");` * Calls to `define(...)` -* Documentation describing how to `require` the library +* 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. +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. -### Template +### Global Library Template The template file [`global.d.ts`](./templates/global.d.ts) defines an example library `myLib`. Be sure to read the ["Preventing Name Conflicts" footnote](#preventing-name-conflicts). -## *module* +## Modular Libraries Some libraries only work in a module loader environment. -For example, because `express` only works in NodeJS, - it must be loaded using the CommonJS `require` function. +For example, because `express` only works in Node.js and must be loaded using the CommonJS `require` function. -ECMAScript 2016 (also known as ES2015, ECMAScript 6, ES6), CommonJS, and RequireJS have similar notions of *importing* a *module*. -In JavaScript CommonJS (nodejs), for example, you would write +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 ```ts -var fs = require('fs'); +var fs = require("fs"); ``` In TypeScript or ES6, the `import` keyword serves the same purpose: ```ts -import fs = require('fs'); +import fs = require("fs"); ``` -You'll typically see module libraries include one of these lines in their documentation: +You'll typically see modular libraries include one of these lines in their documentation: ```js var someLib = require('someLib'); @@ -117,14 +111,13 @@ 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. +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 -Module libraries will typically have at least some of the following: +Modular libraries will typically have at least some of the following: -* Unconditional calls to `require` or `define`* +* Unconditional calls to `require` or `define` * Declarations like `import * as a from 'b';` or `export c;` * Assignments to `exports` or `module.exports` @@ -132,19 +125,18 @@ They will rarely have: * Assignments to properties of `window` or `global` -### Examples of Module Libraries +### Examples of Modular Libraries -Many popular nodejs libraries are in the module family, such as [`express`](http://expressjs.com/), [`gulp`](http://gulpjs.com/), and [`request`](https://github.com/request/request). +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). -Many popular libraries, such as [`moment`](http://momentjs.com/), are written this way. -For example, in nodejs, you would write: +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'); +import moment = require("moment"); console.log(moment.format()); ``` @@ -161,27 +153,25 @@ This is an easy-to-spot pattern that looks something like this: ```js (function (root, factory) { - if (typeof define === 'function' && define.amd) { - define(['b'], factory); - } else if (typeof module === 'object' && module.exports) { - module.exports = factory(require('b')); + 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.b); + 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. +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 nodejs" example showing `require` - and a "Using in browser" example showing using a `