All Projects β†’ sindresorhus β†’ Typescript Definition Style Guide

sindresorhus / Typescript Definition Style Guide

Licence: cc-by-4.0
Style guide for adding type definitions to my npm packages

Programming Languages

typescript
32286 projects

Projects that are alternatives of or similar to Typescript Definition Style Guide

smoothie
A deliciously scalable and adaptable stylesheet methodology 🍹
Stars: ✭ 27 (-92.48%)
Mutual labels:  style-guide
Riotjs Style Guide
Opinionated RiotJS Style Guide for teams.
Stars: ✭ 288 (-19.78%)
Mutual labels:  style-guide
Git Cop
DEPRECATED: Use Git Lint (https://www.alchemists.io/projects/git-lint) instead.
Stars: ✭ 352 (-1.95%)
Mutual labels:  style-guide
front-end-resources
πŸ“šResources for front-end developer
Stars: ✭ 32 (-91.09%)
Mutual labels:  style-guide
Vuejs Component Style Guide
Vue.js Component Style Guide
Stars: ✭ 2,796 (+678.83%)
Mutual labels:  style-guide
Seek Style Guide
Living style guide for SEEK, powered by React, webpack, CSS Modules and Less.
Stars: ✭ 302 (-15.88%)
Mutual labels:  style-guide
elixir inconsistencies
List of inconsistencies found throughout the Elixir programming language
Stars: ✭ 23 (-93.59%)
Mutual labels:  style-guide
Ruby Style Guide
πŸ“˜ Russian Version: A community-driven Ruby coding style guide.
Stars: ✭ 358 (-0.28%)
Mutual labels:  style-guide
Ruby Style Guide
A community-driven Ruby coding style guide
Stars: ✭ 15,836 (+4311.14%)
Mutual labels:  style-guide
Mdx Go
⚑️ Lightning fast MDX-based dev server for progressive documentation
Stars: ✭ 340 (-5.29%)
Mutual labels:  style-guide
standard-packages
List of packages that use `standard`
Stars: ✭ 32 (-91.09%)
Mutual labels:  style-guide
minitest-style-guide
Best practices for writing your tests
Stars: ✭ 42 (-88.3%)
Mutual labels:  style-guide
Elements Of Python Style
Goes beyond PEP8 to discuss what makes Python code feel great. A Strunk & White for Python.
Stars: ✭ 3,308 (+821.45%)
Mutual labels:  style-guide
ue5-style-guide
An attempt to make Unreal Engine 4 projects more consistent
Stars: ✭ 2,892 (+705.57%)
Mutual labels:  style-guide
Css Style Guide Audit
Audit the CSS on a page to see what elements are using styles from the style guide and which styles are overriding them
Stars: ✭ 353 (-1.67%)
Mutual labels:  style-guide
a-pollo
🎨 The visual CSS style guide for teams
Stars: ✭ 14 (-96.1%)
Mutual labels:  style-guide
Awesome Standard
Documenting the explosion of packages in the standard ecosystem!
Stars: ✭ 300 (-16.43%)
Mutual labels:  style-guide
Active Job Style Guide
This Background Jobs style guide is a list of best practices working with Ruby background jobs.
Stars: ✭ 355 (-1.11%)
Mutual labels:  style-guide
Zh Style Guide
An open-source style guide for writing Chinese technical documents: https://zh-style-guide.readthedocs.io
Stars: ✭ 353 (-1.67%)
Mutual labels:  style-guide
Ios Handbook
Guidelines and best practices for excellent iOS apps
Stars: ✭ 337 (-6.13%)
Mutual labels:  style-guide

TypeScript Definition Style Guide

Style guide for adding type definitions to my npm packages

Open an issue if anything is unclear or if you have ideas for other checklist items.

Checklist

  • Use tab-indentation and semicolons.
  • The definition should target the latest TypeScript version.
  • Exported properties/methods should be documented (see below).
  • The definition should be tested (see below).
  • When you have to use Node.js types, install the @types/node package as a dev dependency and add the /// <reference types="node"/> triple-slash reference to the top of the definition file.
  • When you have to use DOM types (Window, Document, …), add the /// <reference lib="dom"/> triple-slash reference to the top of the definition file.
  • Third-party library types (everything in the @types/* namespace) must be installed as direct dependencies, if required. Prefer imports over triple-slash references. You usually only need a triple-slash reference for a third-party library if it exposes interfaces only in the global namespace.
  • Ensure you're not falling for any of the common mistakes.
  • For packages with a default export, use export = foo; syntax. Only use export foo ... syntax if the package has no default export. Do not add a namespace unless you have to export types or interfaces. See more on this topic here.
  • Use the name "types" and not "typings" for the TypeScript definition field in package.json.
  • Place "types" in package.json after all official package properties, but before custom properties, preferably after "dependencies" and/or "devDependencies".
  • If the entry file in the package is named index.js, name the type definition file index.d.ts and put it in root.
    You don't need to add a types field to package.json as TypeScript will infer it from the name.
  • Add the type definition file to the files field in package.json.
  • The pull request should have the title Add TypeScript definition. (Copy-paste it so you don't get it wrong)
  • Help review other pull requests that adds a type definition.

Check out this and this example for how it should be done.

Types

  • All types used in the public interface should be added to an exported namespace or export'ed.
  • Types should not have namespaced names; interface Options {}, not interface FooOptions {}, unless there are multiple Options interfaces.
  • Use the array shorthand type notation; number[], not Array<number>.
  • Use the readonly number[] notation; not ReadonlyArray<number>.
  • Prefer using the unknown type instead of any whenever possible.
  • Don't use abbreviation for type/variable/function names; function foo(options: Options), not function foo(opts: Opts).
  • When there are more than one generic type variable in a method, they should have descriptive names; type Mapper<Element, NewElement> = …, not type Mapper<T, U> = ….
  • Don't prefix the name of interfaces with I; Options, not IOptions.
  • Imports, destructuring, and object literals should not have spaces around the identifier; {foo}, not { foo }.
  • Don't use permissive types like object or Function. Use specific type-signatures like {[key: string]: number} or (input: string) => boolean;.
  • Use {[key: string]: any} for accepting objects with string index type and {[key: string]: unknown} for returning such objects. The reason any is used for assignment is that TypeScript has special behavior for it:

    The index signature {[key: string]: any} in TypeScript behaves specially: it’s a valid assignment target for any object type. This is a special rule, since types with index signatures don’t normally produce this behavior.

Prefer read-only values

Make something read-only when it's not meant to be modified. This is usually the case for return values and option interfaces. Get familiar with the readonly keyword for properties and array/tuple types. There's also a Readonly type to mark all properties as readonly.

Before:

interface Point {
	x: number;
	y: number;
	children: Point[];
}

After:

interface Point {
	readonly x: number;
	readonly y: number;
	readonly children: readonly Point[];
}

Import types explicitly

Don't use implicit global types except for built-ins or when they can't be imported.

Before:

export function getWindow(): Electron.BrowserWindow;

After:

import {BrowserWindow} from 'electron';

export function getWindow(): BrowserWindow;

Readable named imports

Use a readable name when using named imports.

Before:

import {Writable} from 'stream';

After:

import {Writable as WritableStream} from 'stream';

Documentation

Exported definitions should be documented with TSDoc. You can borrow text from the readme.

Example:

/// <reference lib="dom"/>

declare namespace add {
	interface Options {
		/**
		Allow negative numbers.

		@default true
		*/
		allowNegative?: boolean;

		/**
		Has the ultimate foo.

		Note: Only use this for good.

		@default false
		*/
		hasFoo?: boolean;

		/**
		Where to save.

		Default: [User's downloads directory](https://example.com)

		@example
		```
		import add = require('add');

		add(1, 2, {saveDirectory: '/my/awesome/dir'})
		```
		*/
		saveDirectory?: string;
	}
}

declare const add: {
	/**
	Add two numbers together.

	@param x - The first number to add.
	@param y - The second number to add.
	@returns The sum of `x` and `y`.
	*/
	(x: number, y: number, options?: add.Options): number;

	/**
	Reload the specified `BrowserWindow` instance or the focused one.

	@param window - Default: `BrowserWindow.getFocusedWindow()`
	*/
	refresh(window?: BrowserWindow): void;
}

export = add;

Note:

  • Don't prefix lines with *.
  • Don't hard-wrap.
  • Put an empty line between interface entries.
  • Sentences should start with an uppercase character and end in a dot.
  • There's an empty line after the function description.
  • Parameters and the return value should be documented.
  • There's a dash after the parameter name.
  • @param should not include the parameter type.
  • If the parameter description just repeats the parameter name, leave it out.
  • If the parameter is options it doesn't need a description.
  • If the function returns void or a wrapped void like Promise<void>, leave out @returns.
  • If you include an @example, there should be a newline above it. The example itself should be wrapped with triple backticks (```).
  • If the API accepts an options-object, define an Options interface as seen above. Document default option values using the @default tag (since interfaces cannot have default values). If the default needs to be a description instead of a basic value, use the formatting Default: Lorem Ipsum..
  • Use @returns, not @return.
  • Ambient declarations can't have default parameters, so in the case of a default method parameter, document it in the parameter docs instead, as seen in the above example.
  • @returns should not duplicate the type information unless it's impossible to describe it without.
    • @returns A boolean of whether it was enabled. β†’ @returns Whether it was enabled.

Code examples

  • Include as many code examples as possible. Borrow from the readme.
  • Code examples should be fully functional and should include the import statement.

Testing

The type definition should be tested with tsd. Example of how to integrate it.

Example:

import {expectType} from 'tsd';
import delay from '.';

expectType<Promise<void>>(delay(200));

expectType<Promise<string>>(delay(200, {value: 'πŸ¦„'}));
expectType<Promise<number>>(delay(200, {value: 0}));

expectType<Promise<never>>(delay.reject(200, {value: 'πŸ¦„'}));
expectType<Promise<never>>(delay.reject(200, {value: 0}));

When it makes sense, also add a negative test using expectError().

Note:

  • The test file should be named index.test-d.ts.
  • tsd supports top-level await.
  • When testing promise-returning functions, don't use the await keyword. Instead, directly assert for a Promise, like in the example above. When you use await, your function can potentially return a bare value without being wrapped in a Promise, since await will happily accept non-Promise values, rendering your test meaningless.
  • Use const assertions when you need to pass literal or readonly typed values to functions in your tests.
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].