├── .npmrc ├── .gitattributes ├── .gitignore ├── .vscode └── settings.json ├── .github ├── funding.yml ├── security.md ├── pull_request_template.md └── contributing.md ├── .travis.yml ├── media ├── logo.png ├── logo.sketch ├── logo@2x.png ├── readme.md └── logo.svg ├── runAddExtensions.sh ├── test-d ├── except.ts ├── promisable.ts ├── mutable.ts ├── merge.ts ├── async-return-type.ts ├── value-of.ts ├── stringified.ts ├── index.ts ├── union-to-intersection.ts ├── fixed-length-array.ts ├── conditional-keys.ts ├── class.ts ├── promise-value.ts ├── tsconfig-json.ts ├── opaque.ts ├── merge-exclusive.ts ├── conditional-pick.ts ├── require-exactly-one.ts ├── set-required.ts ├── conditional-except.ts ├── set-optional.ts ├── require-at-least-one.ts ├── readonly-deep.ts ├── partial-deep.ts └── package-json.ts ├── .editorconfig ├── source ├── stringified.d.ts ├── merge.d.ts ├── async-return-type.d.ts ├── promisable.d.ts ├── mutable.d.ts ├── require-at-least-one.d.ts ├── except.d.ts ├── value-of.d.ts ├── conditional-pick.d.ts ├── promise-value.d.ts ├── set-optional.d.ts ├── set-required.d.ts ├── conditional-except.d.ts ├── literal-union.d.ts ├── conditional-keys.d.ts ├── require-exactly-one.d.ts ├── merge-exclusive.d.ts ├── fixed-length-array.d.ts ├── readonly-deep.d.ts ├── union-to-intersection.d.ts ├── basic.d.ts ├── partial-deep.d.ts ├── opaque.d.ts ├── package-json.d.ts └── tsconfig-json.d.ts ├── package.json ├── license ├── scripts └── addExtensionInFiles.ts ├── index.d.ts ├── mod.ts ├── license-cc0 └── readme.md /.npmrc: -------------------------------------------------------------------------------- 1 | package-lock=false 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | yarn.lock 3 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "deno.enable": true 3 | } 4 | -------------------------------------------------------------------------------- /.github/funding.yml: -------------------------------------------------------------------------------- 1 | github: sindresorhus 2 | tidelift: npm/type-fest 3 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - '12' 4 | - '10' 5 | -------------------------------------------------------------------------------- /media/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/denofn/type-fest/HEAD/media/logo.png -------------------------------------------------------------------------------- /media/logo.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/denofn/type-fest/HEAD/media/logo.sketch -------------------------------------------------------------------------------- /media/logo@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/denofn/type-fest/HEAD/media/logo@2x.png -------------------------------------------------------------------------------- /runAddExtensions.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | deno run --allow-read --allow-write scripts/addExtensionInFiles.ts 3 | -------------------------------------------------------------------------------- /media/readme.md: -------------------------------------------------------------------------------- 1 | # Media 2 | 3 | ## Attribution 4 | 5 | ### Fireworks vector graphic 6 | 7 | [Free Vectors via Vecteezy!](https://www.vecteezy.com) 8 | -------------------------------------------------------------------------------- /test-d/except.ts: -------------------------------------------------------------------------------- 1 | import {expectType} from 'tsd'; 2 | import {Except} from '..'; 3 | 4 | declare const except: Except<{a: number; b: string}, 'b'>; 5 | expectType<{a: number}>(except); 6 | -------------------------------------------------------------------------------- /test-d/promisable.ts: -------------------------------------------------------------------------------- 1 | import {expectType} from 'tsd'; 2 | import {Promisable} from '..'; 3 | 4 | declare const promisable: Promisable; 5 | expectType | string>(promisable); 6 | -------------------------------------------------------------------------------- /.github/security.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure. 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = tab 5 | end_of_line = lf 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | 10 | [*.yml] 11 | indent_style = space 12 | indent_size = 2 13 | -------------------------------------------------------------------------------- /test-d/mutable.ts: -------------------------------------------------------------------------------- 1 | import {Mutable} from '..'; 2 | 3 | type Foo = { 4 | readonly a: number; 5 | readonly b: string; 6 | }; 7 | 8 | const ab: Mutable = {a: 1, b: '2'}; 9 | ab.a = 2; 10 | const ab2: Mutable> = ab; 11 | ab2.a = 2; 12 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | 9 | -------------------------------------------------------------------------------- /test-d/merge.ts: -------------------------------------------------------------------------------- 1 | import {expectAssignable} from 'tsd'; 2 | import {Merge} from '..'; 3 | 4 | type Foo = { 5 | a: number; 6 | b: string; 7 | }; 8 | 9 | type Bar = { 10 | b: number; 11 | }; 12 | 13 | const ab: Merge = {a: 1, b: 2}; 14 | expectAssignable<{a: number; b: number}>(ab); 15 | -------------------------------------------------------------------------------- /test-d/async-return-type.ts: -------------------------------------------------------------------------------- 1 | import {expectType, expectError} from 'tsd'; 2 | import {AsyncReturnType} from '..'; 3 | 4 | async function asyncFunction(): Promise { 5 | return Promise.resolve(2); 6 | } 7 | 8 | type Value = AsyncReturnType; 9 | 10 | asyncFunction().then(value => { 11 | expectType(value); 12 | expectError(value); 13 | }); 14 | -------------------------------------------------------------------------------- /test-d/value-of.ts: -------------------------------------------------------------------------------- 1 | import {expectType, expectError, expectAssignable} from 'tsd'; 2 | import {ValueOf} from '..'; 3 | 4 | const value: ValueOf<{a: 1; b: 2; c: 3}> = 3; 5 | const valueRestricted: ValueOf<{a: 1; b: 2; c: 3}, 'a'> = 1; 6 | 7 | expectAssignable<1 | 2 | 3>(value); 8 | expectError<4>(value); 9 | 10 | expectType<1>(valueRestricted); 11 | expectError<2>(valueRestricted); 12 | expectError<4>(valueRestricted); 13 | -------------------------------------------------------------------------------- /test-d/stringified.ts: -------------------------------------------------------------------------------- 1 | import {expectType, expectError} from 'tsd'; 2 | import {Stringified} from '..'; 3 | 4 | declare const stringified: Stringified<{a: number; b: string}>; 5 | expectType<{a: string; b: string}>(stringified); 6 | 7 | type Car = { 8 | model: string; 9 | speed: number; 10 | }; 11 | expectError>({model: 'Foo', speed: 101}); 12 | expectType>({model: 'Foo', speed: '101'}); 13 | -------------------------------------------------------------------------------- /test-d/index.ts: -------------------------------------------------------------------------------- 1 | import {expectType} from 'tsd'; 2 | import {ObservableLike} from '..'; 3 | 4 | // eslint-disable-next-line no-use-extend-native/no-use-extend-native 5 | expectType(Symbol.observable); 6 | 7 | const observable = (null as any) as ObservableLike; 8 | 9 | observable.subscribe(() => {}); // eslint-disable-line @typescript-eslint/no-empty-function 10 | observable.subscribe(value => expectType(value)); 11 | -------------------------------------------------------------------------------- /test-d/union-to-intersection.ts: -------------------------------------------------------------------------------- 1 | import {expectAssignable} from 'tsd'; 2 | import {UnionToIntersection} from '..'; 3 | 4 | declare const intersection1: UnionToIntersection<{a: string} | {b: number}>; 5 | expectAssignable<{a: string; b: number}>(intersection1); 6 | 7 | // Creates a union of matching properties. 8 | declare const intersection2: UnionToIntersection<{a: string} | {b: number} | {a: () => void}>; 9 | expectAssignable<{a: string | (() => void); b: number}>(intersection2); 10 | -------------------------------------------------------------------------------- /test-d/fixed-length-array.ts: -------------------------------------------------------------------------------- 1 | import {expectAssignable, expectNotAssignable} from 'tsd'; 2 | import {FixedLengthArray} from '..'; 3 | 4 | type FixedToThreeStrings = FixedLengthArray; 5 | 6 | expectAssignable(['a', 'b', 'c']); 7 | 8 | expectNotAssignable(['a', 'b', 123]); 9 | expectNotAssignable(['a']); 10 | expectNotAssignable(['a', 'b']); 11 | expectNotAssignable(['a', 'b', 'c', 'd']); 12 | -------------------------------------------------------------------------------- /test-d/conditional-keys.ts: -------------------------------------------------------------------------------- 1 | import {expectType} from 'tsd'; 2 | import {ConditionalKeys} from '..'; 3 | 4 | interface Example { 5 | a: string; 6 | b?: string | number; 7 | c?: string; 8 | d: Record; 9 | } 10 | 11 | declare const exampleConditionalKeys: ConditionalKeys; 12 | expectType<'a'>(exampleConditionalKeys); 13 | 14 | declare const exampleConditionalKeysWithUndefined: ConditionalKeys; 15 | expectType<'a' | 'c'>(exampleConditionalKeysWithUndefined); 16 | -------------------------------------------------------------------------------- /source/stringified.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | Create a type with the keys of the given type changed to `string` type. 3 | 4 | Use-case: Changing interface values to strings in order to use them in a form model. 5 | 6 | @example 7 | ``` 8 | import {Stringified} from 'type-fest'; 9 | 10 | type Car { 11 | model: string; 12 | speed: number; 13 | } 14 | 15 | const carForm: Stringified = { 16 | model: 'Foo', 17 | speed: '101' 18 | }; 19 | ``` 20 | */ 21 | export type Stringified = {[KeyType in keyof ObjectType]: string}; 22 | -------------------------------------------------------------------------------- /test-d/class.ts: -------------------------------------------------------------------------------- 1 | import {expectError} from 'tsd'; 2 | import {Class} from '..'; 3 | 4 | class Foo { 5 | constructor(x: number, y: any) { 6 | console.log(x, y); 7 | } 8 | 9 | // eslint-disable-next-line @typescript-eslint/no-empty-function 10 | method(): void {} 11 | } 12 | 13 | function fn(Cls: Class): Foo { 14 | return new Cls(1, '', 123); 15 | } 16 | 17 | function fn2(Cls: Class): Foo { 18 | expectError(new Cls(1, '')); 19 | return new Cls(1, 2); 20 | } 21 | 22 | fn(Foo); 23 | fn2(Foo); 24 | -------------------------------------------------------------------------------- /source/merge.d.ts: -------------------------------------------------------------------------------- 1 | import type {Except} from './except.d.ts'; 2 | 3 | /** 4 | Merge two types into a new type. Keys of the second type overrides keys of the first type. 5 | 6 | @example 7 | ``` 8 | import type {Merge} from 'type-fest'; 9 | 10 | type Foo = { 11 | a: number; 12 | b: string; 13 | }; 14 | 15 | type Bar = { 16 | b: number; 17 | }; 18 | 19 | const ab: Merge = {a: 1, b: 2}; 20 | ``` 21 | */ 22 | export type Merge = Except> & SecondType; 23 | -------------------------------------------------------------------------------- /test-d/promise-value.ts: -------------------------------------------------------------------------------- 1 | import {expectAssignable} from 'tsd'; 2 | import {PromiseValue} from '..'; 3 | 4 | type NumberPromise = Promise; 5 | type NestedPromise = Promise; 6 | type Otherwise = object; 7 | 8 | // Test the normal behaviour. 9 | expectAssignable>(2); 10 | 11 | // Test the nested behaviour. 12 | expectAssignable>(2); 13 | 14 | // Test what happens when the `PromiseValue` type is not handed a `Promise` type. 15 | expectAssignable>(2); 16 | 17 | // Test the `Otherwise` generic parameter. 18 | expectAssignable>({}); 19 | -------------------------------------------------------------------------------- /test-d/tsconfig-json.ts: -------------------------------------------------------------------------------- 1 | import {expectType} from 'tsd'; 2 | import {TsConfigJson} from '..'; 3 | 4 | const tsConfig: TsConfigJson = {}; 5 | 6 | expectType(tsConfig.compileOnSave); 7 | expectType(tsConfig.compilerOptions); 8 | expectType(tsConfig.exclude); 9 | expectType(tsConfig.extends); 10 | expectType(tsConfig.files); 11 | expectType(tsConfig.include); 12 | expectType(tsConfig.references); 13 | expectType(tsConfig.typeAcquisition); 14 | -------------------------------------------------------------------------------- /test-d/opaque.ts: -------------------------------------------------------------------------------- 1 | import {expectAssignable, expectError} from 'tsd'; 2 | import {Opaque} from '..'; 3 | 4 | type Value = Opaque; 5 | 6 | // We make an explicit cast so we can test the value. 7 | const value: Value = 2 as Value; 8 | 9 | // Every opaque type should have a private member with a type of the Token parameter, so the compiler can differentiate separate opaque types. 10 | expectAssignable(value.__opaque__); 11 | 12 | // The underlying type of the value is still a number. 13 | expectAssignable(value); 14 | 15 | // You cannot modify an opaque value. 16 | expectError(value + 2); // eslint-disable-line @typescript-eslint/restrict-plus-operands 17 | -------------------------------------------------------------------------------- /source/async-return-type.d.ts: -------------------------------------------------------------------------------- 1 | import type {PromiseValue} from './promise-value.d.ts'; 2 | 3 | type AsyncFunction = (...args: any[]) => Promise; 4 | 5 | /** 6 | Unwrap the return type of a function that returns a `Promise`. 7 | 8 | There has been [discussion](https://github.com/microsoft/TypeScript/pull/35998) about implementing this type in TypeScript. 9 | 10 | @example 11 | ```ts 12 | import type {AsyncReturnType} from 'type-fest'; 13 | import type {asyncFunction} from 'api'; 14 | 15 | // This type resolves to the unwrapped return type of `asyncFunction`. 16 | type Value = AsyncReturnType; 17 | 18 | async function doSomething(value: Value) {} 19 | 20 | asyncFunction().then(value => doSomething(value)); 21 | ``` 22 | */ 23 | export type AsyncReturnType = PromiseValue>; 24 | -------------------------------------------------------------------------------- /test-d/merge-exclusive.ts: -------------------------------------------------------------------------------- 1 | import {expectError, expectAssignable} from 'tsd'; 2 | import {MergeExclusive} from '..'; 3 | 4 | interface BaseOptions { 5 | option?: string; 6 | } 7 | 8 | interface ExclusiveVariation1 extends BaseOptions { 9 | exclusive1: boolean; 10 | } 11 | 12 | interface ExclusiveVariation2 extends BaseOptions { 13 | exclusive2: number; 14 | } 15 | 16 | type Options = MergeExclusive; 17 | 18 | const exclusiveVariation1: Options = {exclusive1: true}; 19 | const exclusiveVariation2: Options = {exclusive2: 1}; 20 | 21 | expectAssignable<{option?: string; exclusive1: boolean; exclusive2?: string}>( 22 | exclusiveVariation1 23 | ); 24 | expectAssignable<{option?: string; exclusive1?: string; exclusive2: number}>( 25 | exclusiveVariation2 26 | ); 27 | 28 | expectError({exclusive1: true, exclusive2: 1}); 29 | -------------------------------------------------------------------------------- /source/promisable.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | Create a type that represents either the value or the value wrapped in `PromiseLike`. 3 | 4 | Use-cases: 5 | - A function accepts a callback that may either return a value synchronously or may return a promised value. 6 | - This type could be the return type of `Promise#then()`, `Promise#catch()`, and `Promise#finally()` callbacks. 7 | 8 | Please upvote [this issue](https://github.com/microsoft/TypeScript/issues/31394) if you want to have this type as a built-in in TypeScript. 9 | 10 | @example 11 | ``` 12 | import {Promisable} from 'type-fest'; 13 | 14 | async function logger(getLogEntry: () => Promisable): Promise { 15 | const entry = await getLogEntry(); 16 | console.log(entry); 17 | } 18 | 19 | logger(() => 'foo'); 20 | logger(() => Promise.resolve('bar')); 21 | ``` 22 | */ 23 | export type Promisable = T | PromiseLike; 24 | -------------------------------------------------------------------------------- /test-d/conditional-pick.ts: -------------------------------------------------------------------------------- 1 | import {expectType} from 'tsd'; 2 | import {ConditionalPick, Primitive} from '..'; 3 | 4 | class Awesome { 5 | name!: string; 6 | successes!: number; 7 | failures!: bigint; 8 | 9 | run(): void { 10 | // Empty 11 | } 12 | } 13 | 14 | interface Example { 15 | a: string; 16 | b?: string | number; 17 | c?: string; 18 | d: Record; 19 | } 20 | 21 | declare const exampleConditionalPick: ConditionalPick; 22 | expectType< {a: string}>(exampleConditionalPick); 23 | 24 | declare const awesomeConditionalPick: ConditionalPick; 25 | expectType<{name: string; successes: number; failures: bigint}>(awesomeConditionalPick); 26 | 27 | declare const exampleConditionalPickWithUndefined: ConditionalPick; 28 | expectType<{a: string; c?: string}>(exampleConditionalPickWithUndefined); 29 | -------------------------------------------------------------------------------- /test-d/require-exactly-one.ts: -------------------------------------------------------------------------------- 1 | import {expectError, expectAssignable} from 'tsd'; 2 | import {RequireExactlyOne} from '..'; 3 | 4 | type SystemMessages = { 5 | default: string; 6 | 7 | macos: string; 8 | linux: string; 9 | 10 | optional?: string; 11 | }; 12 | 13 | type ValidMessages = RequireExactlyOne; 14 | const test = (_: ValidMessages): void => {}; // eslint-disable-line @typescript-eslint/no-empty-function 15 | 16 | test({macos: 'hey', default: 'hello'}); 17 | test({linux: 'sup', optional: 'howdy', default: 'hello'}); 18 | 19 | expectError(test({})); 20 | expectError(test({macos: 'hey', linux: 'sup', default: 'hello'})); 21 | 22 | declare const oneWithoutKeys: RequireExactlyOne<{a: number; b: number}>; 23 | expectAssignable<{a: number} | {b: number}>(oneWithoutKeys); 24 | expectError(expectAssignable<{a: number; b: number}>(oneWithoutKeys)); 25 | -------------------------------------------------------------------------------- /test-d/set-required.ts: -------------------------------------------------------------------------------- 1 | import {expectType, expectError} from 'tsd'; 2 | import {SetRequired} from '..'; 3 | 4 | // Update one required and one optional to required. 5 | declare const variation1: SetRequired<{a?: number; b: string; c?: boolean}, 'b' | 'c'>; 6 | expectType<{a?: number; b: string; c: boolean}>(variation1); 7 | 8 | // Update two optional to required. 9 | declare const variation2: SetRequired<{a?: number; b?: string; c?: boolean}, 'a' | 'b'>; 10 | expectType<{a: number; b: string; c?: boolean}>(variation2); 11 | 12 | // Three required remain required. 13 | declare const variation3: SetRequired<{a: number; b: string; c: boolean}, 'a' | 'b' | 'c'>; 14 | expectType<{a: number; b: string; c: boolean}>(variation3); 15 | 16 | // Fail if type changes even if optional is right. 17 | declare const variation4: SetRequired<{a?: number; b: string; c?: boolean}, 'b' | 'c'>; 18 | expectError<{a?: boolean; b: string; c: boolean}>(variation4); 19 | -------------------------------------------------------------------------------- /test-d/conditional-except.ts: -------------------------------------------------------------------------------- 1 | import {expectType} from 'tsd'; 2 | import {ConditionalExcept, Primitive} from '..'; 3 | 4 | class Awesome { 5 | name!: string; 6 | successes!: number; 7 | failures!: bigint; 8 | 9 | run(): void { 10 | // Empty 11 | } 12 | } 13 | 14 | interface Example { 15 | a: string; 16 | b?: string | number; 17 | c?: string; 18 | d: Record; 19 | } 20 | 21 | declare const exampleConditionalExcept: ConditionalExcept; 22 | expectType<{b?: string | number; c?: string; d: Record}>(exampleConditionalExcept); 23 | 24 | declare const awesomeConditionalExcept: ConditionalExcept; 25 | expectType<{run: () => void}>(awesomeConditionalExcept); 26 | 27 | declare const exampleConditionalExceptWithUndefined: ConditionalExcept; 28 | expectType<{b?: string | number; d: Record}>(exampleConditionalExceptWithUndefined); 29 | -------------------------------------------------------------------------------- /test-d/set-optional.ts: -------------------------------------------------------------------------------- 1 | import {expectType, expectError} from 'tsd'; 2 | import {SetOptional} from '..'; 3 | 4 | // Update one required and one optional to optional. 5 | declare const variation1: SetOptional<{a: number; b?: string; c: boolean}, 'b' | 'c'>; 6 | expectType<{a: number; b?: string; c?: boolean}>(variation1); 7 | 8 | // Update two required to optional. 9 | declare const variation2: SetOptional<{a: number; b: string; c: boolean}, 'a' | 'b'>; 10 | expectType<{a?: number; b?: string; c: boolean}>(variation2); 11 | 12 | // Three optional remain optional. 13 | declare const variation3: SetOptional<{a?: number; b?: string; c?: boolean}, 'a' | 'b' | 'c'>; 14 | expectType<{a?: number; b?: string; c?: boolean}>(variation3); 15 | 16 | // Fail if type changes even if optional is right. 17 | declare const variation4: SetOptional<{a: number; b?: string; c: boolean}, 'b' | 'c'>; 18 | expectError<{a: boolean; b?: string; c?: boolean}>(variation4); 19 | -------------------------------------------------------------------------------- /source/mutable.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | Convert an object with `readonly` keys into a mutable object. Inverse of `Readonly`. 3 | 4 | This can be used to [store and mutate options within a class](https://github.com/sindresorhus/pageres/blob/4a5d05fca19a5fbd2f53842cbf3eb7b1b63bddd2/source/index.ts#L72), [edit `readonly` objects within tests](https://stackoverflow.com/questions/50703834), and [construct a `readonly` object within a function](https://github.com/Microsoft/TypeScript/issues/24509). 5 | 6 | @example 7 | ``` 8 | import {Mutable} from 'type-fest'; 9 | 10 | type Foo = { 11 | readonly a: number; 12 | readonly b: string; 13 | }; 14 | 15 | const mutableFoo: Mutable = {a: 1, b: '2'}; 16 | mutableFoo.a = 3; 17 | ``` 18 | */ 19 | export type Mutable = { 20 | // For each `Key` in the keys of `ObjectType`, make a mapped type by removing the `readonly` modifier from the key. 21 | -readonly [KeyType in keyof ObjectType]: ObjectType[KeyType]; 22 | }; 23 | -------------------------------------------------------------------------------- /test-d/require-at-least-one.ts: -------------------------------------------------------------------------------- 1 | import {expectError, expectAssignable} from 'tsd'; 2 | import {RequireAtLeastOne} from '..'; 3 | 4 | type SystemMessages = { 5 | default: string; 6 | 7 | macos?: string; 8 | linux?: string; 9 | windows?: string; 10 | 11 | optional?: string; 12 | }; 13 | 14 | type ValidMessages = RequireAtLeastOne; 15 | const test = (_: ValidMessages): void => {}; // eslint-disable-line @typescript-eslint/no-empty-function 16 | 17 | test({macos: 'hey', default: 'hello'}); 18 | test({linux: 'sup', default: 'hello', optional: 'howdy'}); 19 | test({macos: 'hey', linux: 'sup', windows: 'hi', default: 'hello'}); 20 | 21 | expectError(test({})); 22 | expectError(test({macos: 'hey'})); 23 | expectError(test({default: 'hello'})); 24 | 25 | declare const atLeastOneWithoutKeys: RequireAtLeastOne<{a: number; b: number}>; 26 | expectAssignable<{a: number; b?: number} | {a?: number; b: number}>(atLeastOneWithoutKeys); 27 | -------------------------------------------------------------------------------- /source/require-at-least-one.d.ts: -------------------------------------------------------------------------------- 1 | import type {Except} from './except.d.ts'; 2 | 3 | /** 4 | Create a type that requires at least one of the given keys. The remaining keys are kept as is. 5 | 6 | @example 7 | ``` 8 | import type {RequireAtLeastOne} from 'type-fest'; 9 | 10 | type Responder = { 11 | text?: () => string; 12 | json?: () => string; 13 | 14 | secure?: boolean; 15 | }; 16 | 17 | const responder: RequireAtLeastOne = { 18 | json: () => '{"message": "ok"}', 19 | secure: true 20 | }; 21 | ``` 22 | */ 23 | export type RequireAtLeastOne = 24 | { 25 | // For each Key in KeysType make a mapped type 26 | [Key in KeysType]: ( 27 | // …by picking that Key's type and making it required 28 | Required> 29 | ) 30 | }[KeysType] 31 | // …then, make intersection types by adding the remaining keys to each mapped type. 32 | & Except; 33 | -------------------------------------------------------------------------------- /source/except.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | Create a type from an object type without certain keys. 3 | 4 | This type is a stricter version of [`Omit`](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html#the-omit-helper-type). The `Omit` type does not restrict the omitted keys to be keys present on the given type, while `Except` does. The benefits of a stricter type are avoiding typos and allowing the compiler to pick up on rename refactors automatically. 5 | 6 | Please upvote [this issue](https://github.com/microsoft/TypeScript/issues/30825) if you want to have the stricter version as a built-in in TypeScript. 7 | 8 | @example 9 | ``` 10 | import {Except} from 'type-fest'; 11 | 12 | type Foo = { 13 | a: number; 14 | b: string; 15 | c: boolean; 16 | }; 17 | 18 | type FooWithoutA = Except; 19 | //=> {b: string}; 20 | ``` 21 | */ 22 | export type Except = Pick>; 23 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "type-fest", 3 | "version": "0.16.0", 4 | "description": "A collection of essential TypeScript types", 5 | "license": "(MIT OR CC0-1.0)", 6 | "repository": "sindresorhus/type-fest", 7 | "funding": "https://github.com/sponsors/sindresorhus", 8 | "author": { 9 | "name": "Sindre Sorhus", 10 | "email": "sindresorhus@gmail.com", 11 | "url": "https://sindresorhus.com" 12 | }, 13 | "engines": { 14 | "node": ">=10" 15 | }, 16 | "scripts": { 17 | "test": "xo && tsd" 18 | }, 19 | "files": [ 20 | "index.d.ts", 21 | "source" 22 | ], 23 | "keywords": [ 24 | "typescript", 25 | "ts", 26 | "types", 27 | "utility", 28 | "util", 29 | "utilities", 30 | "omit", 31 | "merge", 32 | "json" 33 | ], 34 | "devDependencies": { 35 | "tsd": "^0.11.0", 36 | "xo": "^0.28.2" 37 | }, 38 | "types": "index.d.ts", 39 | "xo": { 40 | "rules": { 41 | "@typescript-eslint/indent": "off", 42 | "func-call-spacing": "off" 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /source/value-of.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | Create a union of the given object's values, and optionally specify which keys to get the values from. 3 | 4 | Please upvote [this issue](https://github.com/microsoft/TypeScript/issues/31438) if you want to have this type as a built-in in TypeScript. 5 | 6 | @example 7 | ``` 8 | // data.json 9 | { 10 | 'foo': 1, 11 | 'bar': 2, 12 | 'biz': 3 13 | } 14 | 15 | // main.ts 16 | import type {ValueOf} from 'type-fest'; 17 | import type data = require('./data.json'); 18 | 19 | export type function getData(name: string): ValueOf { 20 | return data[name]; 21 | } 22 | 23 | export type function onlyBar(name: string): ValueOf { 24 | return data[name]; 25 | } 26 | 27 | // file.ts 28 | import type {getData, onlyBar} from './main.d.ts'; 29 | 30 | getData('foo'); 31 | //=> 1 32 | 33 | onlyBar('foo'); 34 | //=> TypeError ... 35 | 36 | onlyBar('bar'); 37 | //=> 2 38 | ``` 39 | */ 40 | export type ValueOf = ObjectType[ValueType]; 41 | -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) Sindre Sorhus (https:/sindresorhus.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /source/conditional-pick.d.ts: -------------------------------------------------------------------------------- 1 | import type {ConditionalKeys} from './conditional-keys.d.ts'; 2 | 3 | /** 4 | Pick keys from the shape that matches the given `Condition`. 5 | 6 | This is useful when you want to create a new type from a specific subset of an existing type. For example, you might want to pick all the primitive properties from a class and form a new automatically derived type. 7 | 8 | @example 9 | ``` 10 | import type {Primitive, ConditionalPick} from 'type-fest'; 11 | 12 | class Awesome { 13 | name: string; 14 | successes: number; 15 | failures: bigint; 16 | 17 | run() {} 18 | } 19 | 20 | type PickPrimitivesFromAwesome = ConditionalPick; 21 | //=> {name: string; successes: number; failures: bigint} 22 | ``` 23 | 24 | @example 25 | ``` 26 | import type {ConditionalPick} from 'type-fest'; 27 | 28 | interface Example { 29 | a: string; 30 | b: string | number; 31 | c: () => void; 32 | d: {}; 33 | } 34 | 35 | type StringKeysOnly = ConditionalPick; 36 | //=> {a: string} 37 | ``` 38 | */ 39 | export type ConditionalPick = Pick< 40 | Base, 41 | ConditionalKeys 42 | >; 43 | -------------------------------------------------------------------------------- /source/promise-value.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | Returns the type that is wrapped inside a `Promise` type. 3 | If the type is a nested Promise, it is unwrapped recursively until a non-Promise type is obtained. 4 | If the type is not a `Promise`, the type itself is returned. 5 | 6 | @example 7 | ``` 8 | import {PromiseValue} from 'type-fest'; 9 | 10 | type AsyncData = Promise; 11 | let asyncData: PromiseValue = Promise.resolve('ABC'); 12 | 13 | type Data = PromiseValue; 14 | let data: Data = await asyncData; 15 | 16 | // Here's an example that shows how this type reacts to non-Promise types. 17 | type SyncData = PromiseValue; 18 | let syncData: SyncData = getSyncData(); 19 | 20 | // Here's an example that shows how this type reacts to recursive Promise types. 21 | type RecursiveAsyncData = Promise >; 22 | let recursiveAsyncData: PromiseValue = Promise.resolve(Promise.resolve('ABC')); 23 | ``` 24 | */ 25 | export type PromiseValue = PromiseType extends Promise 26 | ? { 0: PromiseValue; 1: Value }[PromiseType extends Promise ? 0 : 1] 27 | : Otherwise; 28 | -------------------------------------------------------------------------------- /source/set-optional.d.ts: -------------------------------------------------------------------------------- 1 | import type {Except} from './except.d.ts'; 2 | 3 | /** 4 | Create a type that makes the given keys optional. The remaining keys are kept as is. The sister of the `SetRequired` type. 5 | 6 | Use-case: You want to define a single model where the only thing that changes is whether or not some of the keys are optional. 7 | 8 | @example 9 | ``` 10 | import type {SetOptional} from 'type-fest'; 11 | 12 | type Foo = { 13 | a: number; 14 | b?: string; 15 | c: boolean; 16 | } 17 | 18 | type SomeOptional = SetOptional; 19 | // type SomeOptional = { 20 | // a: number; 21 | // b?: string; // Was already optional and still is. 22 | // c?: boolean; // Is now optional. 23 | // } 24 | ``` 25 | */ 26 | export type SetOptional = 27 | // Pick just the keys that are not optional from the base type. 28 | Except & 29 | // Pick the keys that should be optional from the base type and make them optional. 30 | Partial> extends 31 | // If `InferredType` extends the previous, then for each key, use the inferred type key. 32 | infer InferredType 33 | ? {[KeyType in keyof InferredType]: InferredType[KeyType]} 34 | : never; 35 | -------------------------------------------------------------------------------- /source/set-required.d.ts: -------------------------------------------------------------------------------- 1 | import type {Except} from './except.d.ts'; 2 | 3 | /** 4 | Create a type that makes the given keys required. The remaining keys are kept as is. The sister of the `SetOptional` type. 5 | 6 | Use-case: You want to define a single model where the only thing that changes is whether or not some of the keys are required. 7 | 8 | @example 9 | ``` 10 | import type {SetRequired} from 'type-fest'; 11 | 12 | type Foo = { 13 | a?: number; 14 | b: string; 15 | c?: boolean; 16 | } 17 | 18 | type SomeRequired = SetRequired; 19 | // type SomeRequired = { 20 | // a?: number; 21 | // b: string; // Was already required and still is. 22 | // c: boolean; // Is now required. 23 | // } 24 | ``` 25 | */ 26 | export type SetRequired = 27 | // Pick just the keys that are not required from the base type. 28 | Except & 29 | // Pick the keys that should be required from the base type and make them required. 30 | Required> extends 31 | // If `InferredType` extends the previous, then for each key, use the inferred type key. 32 | infer InferredType 33 | ? {[KeyType in keyof InferredType]: InferredType[KeyType]} 34 | : never; 35 | -------------------------------------------------------------------------------- /source/conditional-except.d.ts: -------------------------------------------------------------------------------- 1 | import type {Except} from './except.d.ts'; 2 | import type {ConditionalKeys} from './conditional-keys.d.ts'; 3 | 4 | /** 5 | Exclude keys from a shape that matches the given `Condition`. 6 | 7 | This is useful when you want to create a new type with a specific set of keys from a shape. For example, you might want to exclude all the primitive properties from a class and form a new shape containing everything but the primitive properties. 8 | 9 | @example 10 | ``` 11 | import type {Primitive, ConditionalExcept} from 'type-fest'; 12 | 13 | class Awesome { 14 | name: string; 15 | successes: number; 16 | failures: bigint; 17 | 18 | run() {} 19 | } 20 | 21 | type ExceptPrimitivesFromAwesome = ConditionalExcept; 22 | //=> {run: () => void} 23 | ``` 24 | 25 | @example 26 | ``` 27 | import type {ConditionalExcept} from 'type-fest'; 28 | 29 | interface Example { 30 | a: string; 31 | b: string | number; 32 | c: () => void; 33 | d: {}; 34 | } 35 | 36 | type NonStringKeysOnly = ConditionalExcept; 37 | //=> {b: string | number; c: () => void; d: {}} 38 | ``` 39 | */ 40 | export type ConditionalExcept = Except< 41 | Base, 42 | ConditionalKeys 43 | >; 44 | -------------------------------------------------------------------------------- /source/literal-union.d.ts: -------------------------------------------------------------------------------- 1 | import type {Primitive} from './basic.d.ts'; 2 | 3 | /** 4 | Allows creating a union type by combining primitive types and literal types without sacrificing auto-completion in IDEs for the literal type part of the union. 5 | 6 | Currently, when a union type of a primitive type is combined with literal types, TypeScript loses all information about the combined literals. Thus, when such type is used in an IDE with autocompletion, no suggestions are made for the declared literals. 7 | 8 | This type is a workaround for [Microsoft/TypeScript#29729](https://github.com/Microsoft/TypeScript/issues/29729). It will be removed as soon as it's not needed anymore. 9 | 10 | @example 11 | ``` 12 | import type {LiteralUnion} from 'type-fest'; 13 | 14 | // Before 15 | 16 | type Pet = 'dog' | 'cat' | string; 17 | 18 | const pet: Pet = ''; 19 | // Start typing in your TypeScript-enabled IDE. 20 | // You **will not** get auto-completion for `dog` and `cat` literals. 21 | 22 | // After 23 | 24 | type Pet2 = LiteralUnion<'dog' | 'cat', string>; 25 | 26 | const pet: Pet2 = ''; 27 | // You **will** get auto-completion for `dog` and `cat` literals. 28 | ``` 29 | */ 30 | export type LiteralUnion< 31 | LiteralType extends BaseType, 32 | BaseType extends Primitive 33 | > = LiteralType | (BaseType & {_?: never}); 34 | -------------------------------------------------------------------------------- /scripts/addExtensionInFiles.ts: -------------------------------------------------------------------------------- 1 | function addExtensionInFiles(path: string, target?: string): void { 2 | let file = Deno.readTextFileSync(path); 3 | 4 | const lookup = "from './" 5 | if (!file.includes(lookup)) return; 6 | 7 | const lines = file.split("\n"); 8 | 9 | for (const line of lines) { 10 | let l = line; 11 | 12 | if (line.includes(lookup) && !line.endsWith(".d.ts';")) { 13 | l = l.replace("';", ".d.ts';") 14 | } 15 | 16 | if ( 17 | line.startsWith("import ") 18 | && !line.startsWith("import * ") 19 | && !line.startsWith("import type ") 20 | ) { 21 | l = l.replace("import ", "import type "); 22 | } 23 | 24 | if ( 25 | line.startsWith("export ") 26 | && !line.startsWith("export * ") 27 | && !line.startsWith("export type ") 28 | && !line.startsWith("export interface ") 29 | ) { 30 | l = l.replace("export ", "export type "); 31 | } 32 | 33 | file = file.replace(line, l); 34 | } 35 | 36 | Deno.writeTextFileSync(target ?? path, file); 37 | } 38 | 39 | // index.d.ts 40 | addExtensionInFiles("./index.d.ts", "./mod.ts"); 41 | // addExtensionInFiles("./index.d.ts"); 42 | 43 | const src = Deno.readDirSync("./source"); 44 | for (const srcFile of src) { 45 | if (srcFile.isFile) { 46 | const path = `./source/${srcFile.name}`; 47 | addExtensionInFiles(path); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /.github/contributing.md: -------------------------------------------------------------------------------- 1 | # Contributing guidelines 2 | 3 | ## Submitting a new type 4 | 5 | - One type addition per pull request, unless they are connected. 6 | - Create a new file in the `test-d` directory and write at least one type test. 7 | - See the other tests for inspiration. 8 | - If it makes sense, also write a negative test using [`expectError()`](https://github.com/SamVerschueren/tsd#expecterrorfunction). 9 | - Don't use one-character type names like `T` and `U`. Use descriptive names. See the existing types for inspiration. 10 | - Write a good documentation comment that includes: 11 | - Write a short and clear description of what the type does. 12 | - Write about some real-world use-cases where it can be useful. (It can be hard sometimes for users to see where they would use something) 13 | - Example code block with a realistic example. 14 | - At the bottom, explain how the type works. Some types can be quite advanced and hard to understand. We can use this opportunity to teach users. 15 | - If there has been any discussion somewhere about this type, include a link to it. For example, a discussion on the TypeScript issue tracker. 16 | - If you add any internal helper types, they should still be properly documented and tested. 17 | - Add the type to the readme. 18 | - Run `$ npm test` before submitting and make sure it passes. 19 | - Name the pull request ```Add `TypeName` type```. 20 | -------------------------------------------------------------------------------- /source/conditional-keys.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | Extract the keys from a type where the value type of the key extends the given `Condition`. 3 | 4 | Internally this is used for the `ConditionalPick` and `ConditionalExcept` types. 5 | 6 | @example 7 | ``` 8 | import {ConditionalKeys} from 'type-fest'; 9 | 10 | interface Example { 11 | a: string; 12 | b: string | number; 13 | c?: string; 14 | d: {}; 15 | } 16 | 17 | type StringKeysOnly = ConditionalKeys; 18 | //=> 'a' 19 | ``` 20 | 21 | To support partial types, make sure your `Condition` is a union of undefined (for example, `string | undefined`) as demonstrated below. 22 | 23 | @example 24 | ``` 25 | type StringKeysAndUndefined = ConditionalKeys; 26 | //=> 'a' | 'c' 27 | ``` 28 | */ 29 | export type ConditionalKeys = NonNullable< 30 | // Wrap in `NonNullable` to strip away the `undefined` type from the produced union. 31 | { 32 | // Map through all the keys of the given base type. 33 | [Key in keyof Base]: 34 | // Pick only keys with types extending the given `Condition` type. 35 | Base[Key] extends Condition 36 | // Retain this key since the condition passes. 37 | ? Key 38 | // Discard this key since the condition fails. 39 | : never; 40 | 41 | // Convert the produced object into a union type of the keys which passed the conditional test. 42 | }[keyof Base] 43 | >; 44 | -------------------------------------------------------------------------------- /source/require-exactly-one.d.ts: -------------------------------------------------------------------------------- 1 | // TODO: Remove this when we target TypeScript >=3.5. 2 | type _Omit = Pick>; 3 | 4 | /** 5 | Create a type that requires exactly one of the given keys and disallows more. The remaining keys are kept as is. 6 | 7 | Use-cases: 8 | - Creating interfaces for components that only need one of the keys to display properly. 9 | - Declaring generic keys in a single place for a single use-case that gets narrowed down via `RequireExactlyOne`. 10 | 11 | The caveat with `RequireExactlyOne` is that TypeScript doesn't always know at compile time every key that will exist at runtime. Therefore `RequireExactlyOne` can't do anything to prevent extra keys it doesn't know about. 12 | 13 | @example 14 | ``` 15 | import {RequireExactlyOne} from 'type-fest'; 16 | 17 | type Responder = { 18 | text: () => string; 19 | json: () => string; 20 | secure: boolean; 21 | }; 22 | 23 | const responder: RequireExactlyOne = { 24 | // Adding a `text` key here would cause a compile error. 25 | 26 | json: () => '{"message": "ok"}', 27 | secure: true 28 | }; 29 | ``` 30 | */ 31 | export type RequireExactlyOne = 32 | {[Key in KeysType]: ( 33 | Required> & 34 | Partial, never>> 35 | )}[KeysType] & _Omit; 36 | -------------------------------------------------------------------------------- /source/merge-exclusive.d.ts: -------------------------------------------------------------------------------- 1 | // Helper type. Not useful on its own. 2 | type Without = {[KeyType in Exclude]?: never}; 3 | 4 | /** 5 | Create a type that has mutually exclusive keys. 6 | 7 | This type was inspired by [this comment](https://github.com/Microsoft/TypeScript/issues/14094#issuecomment-373782604). 8 | 9 | This type works with a helper type, called `Without`. `Without` produces a type that has only keys from `FirstType` which are not present on `SecondType` and sets the value type for these keys to `never`. This helper type is then used in `MergeExclusive` to remove keys from either `FirstType` or `SecondType`. 10 | 11 | @example 12 | ``` 13 | import {MergeExclusive} from 'type-fest'; 14 | 15 | interface ExclusiveVariation1 { 16 | exclusive1: boolean; 17 | } 18 | 19 | interface ExclusiveVariation2 { 20 | exclusive2: string; 21 | } 22 | 23 | type ExclusiveOptions = MergeExclusive; 24 | 25 | let exclusiveOptions: ExclusiveOptions; 26 | 27 | exclusiveOptions = {exclusive1: true}; 28 | //=> Works 29 | exclusiveOptions = {exclusive2: 'hi'}; 30 | //=> Works 31 | exclusiveOptions = {exclusive1: true, exclusive2: 'hi'}; 32 | //=> Error 33 | ``` 34 | */ 35 | export type MergeExclusive = 36 | (FirstType | SecondType) extends object ? 37 | (Without & SecondType) | (Without & FirstType) : 38 | FirstType | SecondType; 39 | 40 | -------------------------------------------------------------------------------- /index.d.ts: -------------------------------------------------------------------------------- 1 | // Basic 2 | export { 3 | Primitive, 4 | Class, 5 | TypedArray, 6 | JsonObject, 7 | JsonArray, 8 | JsonValue, 9 | ObservableLike 10 | } from './source/basic'; 11 | 12 | // Utilities 13 | export {Except} from './source/except'; 14 | export {Mutable} from './source/mutable'; 15 | export {Merge} from './source/merge'; 16 | export {MergeExclusive} from './source/merge-exclusive'; 17 | export {RequireAtLeastOne} from './source/require-at-least-one'; 18 | export {RequireExactlyOne} from './source/require-exactly-one'; 19 | export {PartialDeep} from './source/partial-deep'; 20 | export {ReadonlyDeep} from './source/readonly-deep'; 21 | export {LiteralUnion} from './source/literal-union'; 22 | export {Promisable} from './source/promisable'; 23 | export {Opaque} from './source/opaque'; 24 | export {SetOptional} from './source/set-optional'; 25 | export {SetRequired} from './source/set-required'; 26 | export {ValueOf} from './source/value-of'; 27 | export {PromiseValue} from './source/promise-value'; 28 | export {AsyncReturnType} from './source/async-return-type'; 29 | export {ConditionalExcept} from './source/conditional-except'; 30 | export {ConditionalKeys} from './source/conditional-keys'; 31 | export {ConditionalPick} from './source/conditional-pick'; 32 | export {UnionToIntersection} from './source/union-to-intersection'; 33 | export {Stringified} from './source/stringified'; 34 | export {FixedLengthArray} from './source/fixed-length-array'; 35 | 36 | // Miscellaneous 37 | export {PackageJson} from './source/package-json'; 38 | export {TsConfigJson} from './source/tsconfig-json'; 39 | -------------------------------------------------------------------------------- /source/fixed-length-array.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | Methods to exclude. 3 | */ 4 | type ArrayLengthMutationKeys = 'splice' | 'push' | 'pop' | 'shift' | 'unshift'; 5 | 6 | /** 7 | Create a type that represents an array of the given type and length. The array's length and the `Array` prototype methods that manipulate its length are excluded in the resulting type. 8 | 9 | Please participate in [this issue](https://github.com/microsoft/TypeScript/issues/26223) if you want to have a similiar type built into TypeScript. 10 | 11 | Use-cases: 12 | - Declaring fixed-length tuples or arrays with a large number of items. 13 | - Creating a range union (for example, `0 | 1 | 2 | 3 | 4` from the keys of such a type) without having to resort to recursive types. 14 | - Creating an array of coordinates with a static length, for example, length of 3 for a 3D vector. 15 | 16 | @example 17 | ``` 18 | import {FixedLengthArray} from 'type-fest'; 19 | 20 | type FencingTeam = FixedLengthArray; 21 | 22 | const guestFencingTeam: FencingTeam = ['Josh', 'Michael', 'Robert']; 23 | 24 | const homeFencingTeam: FencingTeam = ['George', 'John']; 25 | //=> error TS2322: Type string[] is not assignable to type 'FencingTeam' 26 | 27 | guestFencingTeam.push('Sam'); 28 | //=> error TS2339: Property 'push' does not exist on type 'FencingTeam' 29 | ``` 30 | */ 31 | export type FixedLengthArray = Pick< 32 | ArrayPrototype, 33 | Exclude 34 | > & { 35 | [index: number]: Element; 36 | [Symbol.iterator]: () => IterableIterator; 37 | readonly length: Length; 38 | }; 39 | -------------------------------------------------------------------------------- /test-d/readonly-deep.ts: -------------------------------------------------------------------------------- 1 | import {expectType, expectError} from 'tsd'; 2 | import {ReadonlyDeep} from '../source/readonly-deep'; 3 | 4 | const data = { 5 | object: { 6 | foo: 'bar' 7 | }, 8 | fn: (_: string) => true, 9 | string: 'foo', 10 | number: 1, 11 | boolean: false, 12 | symbol: Symbol('test'), 13 | null: null, 14 | undefined: undefined, // eslint-disable-line object-shorthand 15 | map: new Map(), 16 | set: new Set(), 17 | array: ['foo'], 18 | tuple: ['foo'] as ['foo'], 19 | readonlyMap: new Map() as ReadonlyMap, 20 | readonlySet: new Set() as ReadonlySet, 21 | readonlyArray: ['foo'] as readonly string[], 22 | readonlyTuple: ['foo'] as const 23 | }; 24 | 25 | const readonlyData: ReadonlyDeep = data; 26 | 27 | readonlyData.fn('foo'); 28 | 29 | expectError(readonlyData.string = 'bar'); 30 | expectType<{readonly foo: string}>(readonlyData.object); 31 | expectType(readonlyData.string); 32 | expectType(readonlyData.number); 33 | expectType(readonlyData.boolean); 34 | expectType(readonlyData.symbol); 35 | expectType(readonlyData.null); 36 | expectType(readonlyData.undefined); 37 | expectType>(readonlyData.map); 38 | expectType>(readonlyData.set); 39 | expectType(readonlyData.array); 40 | expectType(readonlyData.tuple); 41 | expectType>(readonlyData.readonlyMap); 42 | expectType>(readonlyData.readonlySet); 43 | expectType(readonlyData.readonlyArray); 44 | expectType(readonlyData.readonlyTuple); 45 | -------------------------------------------------------------------------------- /mod.ts: -------------------------------------------------------------------------------- 1 | // Basic 2 | export type { 3 | Primitive, 4 | Class, 5 | TypedArray, 6 | JsonObject, 7 | JsonArray, 8 | JsonValue, 9 | ObservableLike 10 | } from './source/basic.d.ts'; 11 | 12 | // Utilities 13 | export type {Except} from './source/except.d.ts'; 14 | export type {Mutable} from './source/mutable.d.ts'; 15 | export type {Merge} from './source/merge.d.ts'; 16 | export type {MergeExclusive} from './source/merge-exclusive.d.ts'; 17 | export type {RequireAtLeastOne} from './source/require-at-least-one.d.ts'; 18 | export type {RequireExactlyOne} from './source/require-exactly-one.d.ts'; 19 | export type {PartialDeep} from './source/partial-deep.d.ts'; 20 | export type {ReadonlyDeep} from './source/readonly-deep.d.ts'; 21 | export type {LiteralUnion} from './source/literal-union.d.ts'; 22 | export type {Promisable} from './source/promisable.d.ts'; 23 | export type {Opaque} from './source/opaque.d.ts'; 24 | export type {SetOptional} from './source/set-optional.d.ts'; 25 | export type {SetRequired} from './source/set-required.d.ts'; 26 | export type {ValueOf} from './source/value-of.d.ts'; 27 | export type {PromiseValue} from './source/promise-value.d.ts'; 28 | export type {AsyncReturnType} from './source/async-return-type.d.ts'; 29 | export type {ConditionalExcept} from './source/conditional-except.d.ts'; 30 | export type {ConditionalKeys} from './source/conditional-keys.d.ts'; 31 | export type {ConditionalPick} from './source/conditional-pick.d.ts'; 32 | export type {UnionToIntersection} from './source/union-to-intersection.d.ts'; 33 | export type {Stringified} from './source/stringified.d.ts'; 34 | export type {FixedLengthArray} from './source/fixed-length-array.d.ts'; 35 | 36 | // Miscellaneous 37 | export type {PackageJson} from './source/package-json.d.ts'; 38 | export type {TsConfigJson} from './source/tsconfig-json.d.ts'; 39 | -------------------------------------------------------------------------------- /source/readonly-deep.d.ts: -------------------------------------------------------------------------------- 1 | import type {Primitive} from './basic.d.ts'; 2 | 3 | /** 4 | Convert `object`s, `Map`s, `Set`s, and `Array`s and all of their keys/elements into immutable structures recursively. 5 | 6 | This is useful when a deeply nested structure needs to be exposed as completely immutable, for example, an imported JSON module or when receiving an API response that is passed around. 7 | 8 | Please upvote [this issue](https://github.com/microsoft/TypeScript/issues/13923) if you want to have this type as a built-in in TypeScript. 9 | 10 | @example 11 | ``` 12 | // data.json 13 | { 14 | "foo": ["bar"] 15 | } 16 | 17 | // main.ts 18 | import type {ReadonlyDeep} from 'type-fest'; 19 | import type dataJson = require('./data.json'); 20 | 21 | const data: ReadonlyDeep = dataJson; 22 | 23 | export type default data; 24 | 25 | // test.ts 26 | import type data from './main.d.ts'; 27 | 28 | data.foo.push('bar'); 29 | //=> error TS2339: Property 'push' does not exist on type 'readonly string[]' 30 | ``` 31 | */ 32 | export type ReadonlyDeep = T extends Primitive | ((...arguments: any[]) => unknown) 33 | ? T 34 | : T extends ReadonlyMap 35 | ? ReadonlyMapDeep 36 | : T extends ReadonlySet 37 | ? ReadonlySetDeep 38 | : T extends object 39 | ? ReadonlyObjectDeep 40 | : unknown; 41 | 42 | /** 43 | Same as `ReadonlyDeep`, but accepts only `ReadonlyMap`s as inputs. Internal helper for `ReadonlyDeep`. 44 | */ 45 | interface ReadonlyMapDeep 46 | extends ReadonlyMap, ReadonlyDeep> {} 47 | 48 | /** 49 | Same as `ReadonlyDeep`, but accepts only `ReadonlySet`s as inputs. Internal helper for `ReadonlyDeep`. 50 | */ 51 | interface ReadonlySetDeep 52 | extends ReadonlySet> {} 53 | 54 | /** 55 | Same as `ReadonlyDeep`, but accepts only `object`s as inputs. Internal helper for `ReadonlyDeep`. 56 | */ 57 | type ReadonlyObjectDeep = { 58 | readonly [KeyType in keyof ObjectType]: ReadonlyDeep 59 | }; 60 | -------------------------------------------------------------------------------- /source/union-to-intersection.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | Convert a union type to an intersection type using [distributive conditional types](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#distributive-conditional-types). 3 | 4 | Inspired by [this Stack Overflow answer](https://stackoverflow.com/a/50375286/2172153). 5 | 6 | @example 7 | ``` 8 | import {UnionToIntersection} from 'type-fest'; 9 | 10 | type Union = {the(): void} | {great(arg: string): void} | {escape: boolean}; 11 | 12 | type Intersection = UnionToIntersection; 13 | //=> {the(): void; great(arg: string): void; escape: boolean}; 14 | ``` 15 | 16 | A more applicable example which could make its way into your library code follows. 17 | 18 | @example 19 | ``` 20 | import {UnionToIntersection} from 'type-fest'; 21 | 22 | class CommandOne { 23 | commands: { 24 | a1: () => undefined, 25 | b1: () => undefined, 26 | } 27 | } 28 | 29 | class CommandTwo { 30 | commands: { 31 | a2: (argA: string) => undefined, 32 | b2: (argB: string) => undefined, 33 | } 34 | } 35 | 36 | const union = [new CommandOne(), new CommandTwo()].map(instance => instance.commands); 37 | type Union = typeof union; 38 | //=> {a1(): void; b1(): void} | {a2(argA: string): void; b2(argB: string): void} 39 | 40 | type Intersection = UnionToIntersection; 41 | //=> {a1(): void; b1(): void; a2(argA: string): void; b2(argB: string): void} 42 | ``` 43 | */ 44 | export type UnionToIntersection = ( 45 | // `extends unknown` is always going to be the case and is used to convert the 46 | // `Union` into a [distributive conditional 47 | // type](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#distributive-conditional-types). 48 | Union extends unknown 49 | // The union type is used as the only argument to a function since the union 50 | // of function arguments is an intersection. 51 | ? (distributedUnion: Union) => void 52 | // This won't happen. 53 | : never 54 | // Infer the `Intersection` type since TypeScript represents the positional 55 | // arguments of unions of functions as an intersection of the union. 56 | ) extends ((mergedIntersection: infer Intersection) => void) 57 | ? Intersection 58 | : never; 59 | -------------------------------------------------------------------------------- /source/basic.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | // TODO: This can just be `export type Primitive = not object` when the `not` keyword is out. 4 | /** 5 | Matches any [primitive value](https://developer.mozilla.org/en-US/docs/Glossary/Primitive). 6 | */ 7 | export type Primitive = 8 | | null 9 | | undefined 10 | | string 11 | | number 12 | | boolean 13 | | symbol 14 | | bigint; 15 | 16 | // TODO: Remove the `= unknown` sometime in the future when most users are on TS 3.5 as it's now the default 17 | /** 18 | Matches a [`class` constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes). 19 | */ 20 | export type Class = new(...arguments_: Arguments) => T; 21 | 22 | /** 23 | Matches any [typed array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray), like `Uint8Array` or `Float64Array`. 24 | */ 25 | export type TypedArray = 26 | | Int8Array 27 | | Uint8Array 28 | | Uint8ClampedArray 29 | | Int16Array 30 | | Uint16Array 31 | | Int32Array 32 | | Uint32Array 33 | | Float32Array 34 | | Float64Array 35 | | BigInt64Array 36 | | BigUint64Array; 37 | 38 | /** 39 | Matches a JSON object. 40 | 41 | This type can be useful to enforce some input to be JSON-compatible or as a super-type to be extended from. Don't use this as a direct return type as the user would have to double-cast it: `jsonObject as unknown as CustomResponse`. Instead, you could extend your CustomResponse type from it to ensure your type only uses JSON-compatible types: `interface CustomResponse extends JsonObject { … }`. 42 | */ 43 | export type JsonObject = {[Key in string]?: JsonValue}; 44 | 45 | /** 46 | Matches a JSON array. 47 | */ 48 | export interface JsonArray extends Array {} 49 | 50 | /** 51 | Matches any valid JSON value. 52 | */ 53 | export type JsonValue = string | number | boolean | null | JsonObject | JsonArray; 54 | 55 | declare global { 56 | interface SymbolConstructor { 57 | readonly observable: symbol; 58 | } 59 | } 60 | 61 | /** 62 | Matches a value that is like an [Observable](https://github.com/tc39/proposal-observable). 63 | */ 64 | export interface ObservableLike { 65 | subscribe(observer: (value: unknown) => void): void; 66 | [Symbol.observable](): ObservableLike; 67 | } 68 | -------------------------------------------------------------------------------- /test-d/partial-deep.ts: -------------------------------------------------------------------------------- 1 | import {expectType, expectError, expectAssignable} from 'tsd'; 2 | import {PartialDeep} from '..'; 3 | 4 | const foo = { 5 | baz: 'fred', 6 | bar: { 7 | function: (_: string): void => {}, // eslint-disable-line @typescript-eslint/no-empty-function 8 | object: {key: 'value'}, 9 | string: 'waldo', 10 | number: 1, 11 | boolean: false, 12 | symbol: Symbol('test'), 13 | null: null, 14 | undefined: undefined, // eslint-disable-line object-shorthand 15 | map: new Map(), 16 | set: new Set(), 17 | array: ['foo'], 18 | tuple: ['foo'] as ['foo'], 19 | readonlyMap: new Map() as ReadonlyMap, 20 | readonlySet: new Set() as ReadonlySet, 21 | readonlyArray: ['foo'] as readonly string[], 22 | readonlyTuple: ['foo'] as const 23 | } 24 | }; 25 | 26 | let partialDeepFoo: PartialDeep = foo; 27 | 28 | expectError(expectType>(partialDeepFoo)); 29 | const partialDeepBar: PartialDeep = foo.bar; 30 | expectType(partialDeepFoo.bar); 31 | expectType<((_: string) => void) | undefined>(partialDeepFoo.bar!.function); 32 | expectAssignable(partialDeepFoo.bar!.object); 33 | expectType(partialDeepFoo.bar!.string); 34 | expectType(partialDeepFoo.bar!.number); 35 | expectType(partialDeepFoo.bar!.boolean); 36 | expectType(partialDeepFoo.bar!.symbol); 37 | expectType(partialDeepFoo.bar!.null); 38 | expectType(partialDeepFoo.bar!.undefined); 39 | expectAssignable | undefined>(partialDeepFoo.bar!.map); 40 | expectAssignable | undefined>(partialDeepFoo.bar!.set); 41 | expectType | undefined>(partialDeepFoo.bar!.array); 42 | expectType<['foo'?] | undefined>(partialDeepFoo.bar!.tuple); 43 | expectAssignable | undefined>(partialDeepFoo.bar!.readonlyMap); 44 | expectAssignable | undefined>(partialDeepFoo.bar!.readonlySet); 45 | expectType | undefined>(partialDeepFoo.bar!.readonlyArray); 46 | expectType(partialDeepFoo.bar!.readonlyTuple); 47 | // Check for compiling with omitting partial keys 48 | partialDeepFoo = {baz: 'fred'}; 49 | partialDeepFoo = {bar: {string: 'waldo'}}; 50 | -------------------------------------------------------------------------------- /source/partial-deep.d.ts: -------------------------------------------------------------------------------- 1 | import type {Primitive} from './basic.d.ts'; 2 | 3 | /** 4 | Create a type from another type with all keys and nested keys set to optional. 5 | 6 | Use-cases: 7 | - Merging a default settings/config object with another object, the second object would be a deep partial of the default object. 8 | - Mocking and testing complex entities, where populating an entire object with its keys would be redundant in terms of the mock or test. 9 | 10 | @example 11 | ``` 12 | import type {PartialDeep} from 'type-fest'; 13 | 14 | const settings: Settings = { 15 | textEditor: { 16 | fontSize: 14; 17 | fontColor: '#000000'; 18 | fontWeight: 400; 19 | } 20 | autocomplete: false; 21 | autosave: true; 22 | }; 23 | 24 | const applySavedSettings = (savedSettings: PartialDeep) => { 25 | return {...settings, ...savedSettings}; 26 | } 27 | 28 | settings = applySavedSettings({textEditor: {fontWeight: 500}}); 29 | ``` 30 | */ 31 | export type PartialDeep = T extends Primitive 32 | ? Partial 33 | : T extends Map 34 | ? PartialMapDeep 35 | : T extends Set 36 | ? PartialSetDeep 37 | : T extends ReadonlyMap 38 | ? PartialReadonlyMapDeep 39 | : T extends ReadonlySet 40 | ? PartialReadonlySetDeep 41 | : T extends ((...arguments: any[]) => unknown) 42 | ? T | undefined 43 | : T extends object 44 | ? PartialObjectDeep 45 | : unknown; 46 | 47 | /** 48 | Same as `PartialDeep`, but accepts only `Map`s and as inputs. Internal helper for `PartialDeep`. 49 | */ 50 | interface PartialMapDeep extends Map, PartialDeep> {} 51 | 52 | /** 53 | Same as `PartialDeep`, but accepts only `Set`s as inputs. Internal helper for `PartialDeep`. 54 | */ 55 | interface PartialSetDeep extends Set> {} 56 | 57 | /** 58 | Same as `PartialDeep`, but accepts only `ReadonlyMap`s as inputs. Internal helper for `PartialDeep`. 59 | */ 60 | interface PartialReadonlyMapDeep extends ReadonlyMap, PartialDeep> {} 61 | 62 | /** 63 | Same as `PartialDeep`, but accepts only `ReadonlySet`s as inputs. Internal helper for `PartialDeep`. 64 | */ 65 | interface PartialReadonlySetDeep extends ReadonlySet> {} 66 | 67 | /** 68 | Same as `PartialDeep`, but accepts only `object`s as inputs. Internal helper for `PartialDeep`. 69 | */ 70 | type PartialObjectDeep = { 71 | [KeyType in keyof ObjectType]?: PartialDeep 72 | }; 73 | -------------------------------------------------------------------------------- /source/opaque.d.ts: -------------------------------------------------------------------------------- 1 | /** 2 | Create an opaque type, which hides its internal details from the public, and can only be created by being used explicitly. 3 | 4 | The generic type parameter can be anything. It doesn't have to be an object. 5 | 6 | [Read more about opaque types.](https://codemix.com/opaque-types-in-javascript/) 7 | 8 | There have been several discussions about adding this feature to TypeScript via the `opaque type` operator, similar to how Flow does it. Unfortunately, nothing has (yet) moved forward: 9 | - [Microsoft/TypeScript#15408](https://github.com/Microsoft/TypeScript/issues/15408) 10 | - [Microsoft/TypeScript#15807](https://github.com/Microsoft/TypeScript/issues/15807) 11 | 12 | @example 13 | ``` 14 | import {Opaque} from 'type-fest'; 15 | 16 | type AccountNumber = Opaque; 17 | type AccountBalance = Opaque; 18 | 19 | // The Token parameter allows the compiler to differentiate between types, whereas "unknown" will not. For example, consider the following structures: 20 | type ThingOne = Opaque; 21 | type ThingTwo = Opaque; 22 | 23 | // To the compiler, these types are allowed to be cast to each other as they have the same underlying type. They are both `string & { __opaque__: unknown }`. 24 | // To avoid this behaviour, you would instead pass the "Token" parameter, like so. 25 | type NewThingOne = Opaque; 26 | type NewThingTwo = Opaque; 27 | 28 | // Now they're completely separate types, so the following will fail to compile. 29 | function createNewThingOne (): NewThingOne { 30 | // As you can see, casting from a string is still allowed. However, you may not cast NewThingOne to NewThingTwo, and vice versa. 31 | return 'new thing one' as NewThingOne; 32 | } 33 | 34 | // This will fail to compile, as they are fundamentally different types. 35 | const thingTwo = createNewThingOne() as NewThingTwo; 36 | 37 | // Here's another example of opaque typing. 38 | function createAccountNumber(): AccountNumber { 39 | return 2 as AccountNumber; 40 | } 41 | 42 | function getMoneyForAccount(accountNumber: AccountNumber): AccountBalance { 43 | return 4 as AccountBalance; 44 | } 45 | 46 | // This will compile successfully. 47 | getMoneyForAccount(createAccountNumber()); 48 | 49 | // But this won't, because it has to be explicitly passed as an `AccountNumber` type. 50 | getMoneyForAccount(2); 51 | 52 | // You can use opaque values like they aren't opaque too. 53 | const accountNumber = createAccountNumber(); 54 | 55 | // This will not compile successfully. 56 | const newAccountNumber = accountNumber + 2; 57 | 58 | // As a side note, you can (and should) use recursive types for your opaque types to make them stronger and hopefully easier to type. 59 | type Person = { 60 | id: Opaque; 61 | name: string; 62 | }; 63 | ``` 64 | */ 65 | export type Opaque = Type & {readonly __opaque__: Token}; 66 | -------------------------------------------------------------------------------- /test-d/package-json.ts: -------------------------------------------------------------------------------- 1 | import {expectType, expectAssignable} from 'tsd'; 2 | import {PackageJson, LiteralUnion} from '..'; 3 | 4 | const packageJson: PackageJson = {}; 5 | 6 | expectType(packageJson.name); 7 | expectType(packageJson.version); 8 | expectType(packageJson.description); 9 | expectType(packageJson.keywords); 10 | expectType | undefined>(packageJson.homepage); 11 | expectType(packageJson.bugs); 12 | expectType(packageJson.license); 13 | expectType | undefined>(packageJson.licenses); 14 | expectType(packageJson.author); 15 | expectType(packageJson.contributors); 16 | expectType(packageJson.maintainers); 17 | expectType(packageJson.files); 18 | expectType(packageJson.main); 19 | expectType(packageJson.bin); 20 | expectType(packageJson.types); 21 | expectType(packageJson.typings); 22 | expectType(packageJson.man); 23 | expectType(packageJson.directories); 24 | expectType<{type: string; url: string; directory?: string} | string | undefined>( 25 | packageJson.repository 26 | ); 27 | expectType(packageJson.scripts); 28 | expectType<{[configKey: string]: unknown} | undefined>(packageJson.config); 29 | expectType(packageJson.dependencies); 30 | expectType(packageJson.devDependencies); 31 | expectType( 32 | packageJson.optionalDependencies 33 | ); 34 | expectType(packageJson.peerDependencies); 35 | expectType(packageJson.bundleDependencies); 36 | expectType(packageJson.bundledDependencies); 37 | expectType(packageJson.resolutions); 38 | expectType(packageJson.workspaces); 39 | expectType<{[engineName: string]: string} | undefined>(packageJson.engines); 40 | expectType(packageJson.engineStrict); 41 | expectAssignable< 42 | | undefined 43 | | Array> 47 | >(packageJson.os); 48 | expectAssignable< 49 | | undefined 50 | | Array> 54 | >(packageJson.cpu); 55 | expectType(packageJson.preferGlobal); 56 | expectType(packageJson.private); 57 | expectType<{[config: string]: unknown} | undefined>(packageJson.publishConfig); 58 | expectType(packageJson.module); 59 | expectType< 60 | | string 61 | | { 62 | [moduleName: string]: string | undefined; 63 | main?: string; 64 | browser?: string; 65 | } 66 | | undefined 67 | >(packageJson.esnext); 68 | expectType(packageJson.jspm); 69 | expectType(packageJson.foo); 70 | -------------------------------------------------------------------------------- /license-cc0: -------------------------------------------------------------------------------- 1 | Creative Commons Legal Code 2 | 3 | CC0 1.0 Universal 4 | 5 | CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE 6 | LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN 7 | ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS 8 | INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES 9 | REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS 10 | PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM 11 | THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED 12 | HEREUNDER. 13 | 14 | Statement of Purpose 15 | 16 | The laws of most jurisdictions throughout the world automatically confer 17 | exclusive Copyright and Related Rights (defined below) upon the creator 18 | and subsequent owner(s) (each and all, an "owner") of an original work of 19 | authorship and/or a database (each, a "Work"). 20 | 21 | Certain owners wish to permanently relinquish those rights to a Work for 22 | the purpose of contributing to a commons of creative, cultural and 23 | scientific works ("Commons") that the public can reliably and without fear 24 | of later claims of infringement build upon, modify, incorporate in other 25 | works, reuse and redistribute as freely as possible in any form whatsoever 26 | and for any purposes, including without limitation commercial purposes. 27 | These owners may contribute to the Commons to promote the ideal of a free 28 | culture and the further production of creative, cultural and scientific 29 | works, or to gain reputation or greater distribution for their Work in 30 | part through the use and efforts of others. 31 | 32 | For these and/or other purposes and motivations, and without any 33 | expectation of additional consideration or compensation, the person 34 | associating CC0 with a Work (the "Affirmer"), to the extent that he or she 35 | is an owner of Copyright and Related Rights in the Work, voluntarily 36 | elects to apply CC0 to the Work and publicly distribute the Work under its 37 | terms, with knowledge of his or her Copyright and Related Rights in the 38 | Work and the meaning and intended legal effect of CC0 on those rights. 39 | 40 | 1. Copyright and Related Rights. A Work made available under CC0 may be 41 | protected by copyright and related or neighboring rights ("Copyright and 42 | Related Rights"). Copyright and Related Rights include, but are not 43 | limited to, the following: 44 | 45 | i. the right to reproduce, adapt, distribute, perform, display, 46 | communicate, and translate a Work; 47 | ii. moral rights retained by the original author(s) and/or performer(s); 48 | iii. publicity and privacy rights pertaining to a person's image or 49 | likeness depicted in a Work; 50 | iv. rights protecting against unfair competition in regards to a Work, 51 | subject to the limitations in paragraph 4(a), below; 52 | v. rights protecting the extraction, dissemination, use and reuse of data 53 | in a Work; 54 | vi. database rights (such as those arising under Directive 96/9/EC of the 55 | European Parliament and of the Council of 11 March 1996 on the legal 56 | protection of databases, and under any national implementation 57 | thereof, including any amended or successor version of such 58 | directive); and 59 | vii. other similar, equivalent or corresponding rights throughout the 60 | world based on applicable law or treaty, and any national 61 | implementations thereof. 62 | 63 | 2. Waiver. To the greatest extent permitted by, but not in contravention 64 | of, applicable law, Affirmer hereby overtly, fully, permanently, 65 | irrevocably and unconditionally waives, abandons, and surrenders all of 66 | Affirmer's Copyright and Related Rights and associated claims and causes 67 | of action, whether now known or unknown (including existing as well as 68 | future claims and causes of action), in the Work (i) in all territories 69 | worldwide, (ii) for the maximum duration provided by applicable law or 70 | treaty (including future time extensions), (iii) in any current or future 71 | medium and for any number of copies, and (iv) for any purpose whatsoever, 72 | including without limitation commercial, advertising or promotional 73 | purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each 74 | member of the public at large and to the detriment of Affirmer's heirs and 75 | successors, fully intending that such Waiver shall not be subject to 76 | revocation, rescission, cancellation, termination, or any other legal or 77 | equitable action to disrupt the quiet enjoyment of the Work by the public 78 | as contemplated by Affirmer's express Statement of Purpose. 79 | 80 | 3. Public License Fallback. Should any part of the Waiver for any reason 81 | be judged legally invalid or ineffective under applicable law, then the 82 | Waiver shall be preserved to the maximum extent permitted taking into 83 | account Affirmer's express Statement of Purpose. In addition, to the 84 | extent the Waiver is so judged Affirmer hereby grants to each affected 85 | person a royalty-free, non transferable, non sublicensable, non exclusive, 86 | irrevocable and unconditional license to exercise Affirmer's Copyright and 87 | Related Rights in the Work (i) in all territories worldwide, (ii) for the 88 | maximum duration provided by applicable law or treaty (including future 89 | time extensions), (iii) in any current or future medium and for any number 90 | of copies, and (iv) for any purpose whatsoever, including without 91 | limitation commercial, advertising or promotional purposes (the 92 | "License"). The License shall be deemed effective as of the date CC0 was 93 | applied by Affirmer to the Work. Should any part of the License for any 94 | reason be judged legally invalid or ineffective under applicable law, such 95 | partial invalidity or ineffectiveness shall not invalidate the remainder 96 | of the License, and in such case Affirmer hereby affirms that he or she 97 | will not (i) exercise any of his or her remaining Copyright and Related 98 | Rights in the Work or (ii) assert any associated claims and causes of 99 | action with respect to the Work, in either case contrary to Affirmer's 100 | express Statement of Purpose. 101 | 102 | 4. Limitations and Disclaimers. 103 | 104 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 105 | surrendered, licensed or otherwise affected by this document. 106 | b. Affirmer offers the Work as-is and makes no representations or 107 | warranties of any kind concerning the Work, express, implied, 108 | statutory or otherwise, including without limitation warranties of 109 | title, merchantability, fitness for a particular purpose, non 110 | infringement, or the absence of latent or other defects, accuracy, or 111 | the present or absence of errors, whether or not discoverable, all to 112 | the greatest extent permissible under applicable law. 113 | c. Affirmer disclaims responsibility for clearing rights of other persons 114 | that may apply to the Work or any use thereof, including without 115 | limitation any person's Copyright and Related Rights in the Work. 116 | Further, Affirmer disclaims responsibility for obtaining any necessary 117 | consents, permissions or other rights required for any use of the 118 | Work. 119 | d. Affirmer understands and acknowledges that Creative Commons is not a 120 | party to this document and has no duty or obligation with respect to 121 | this CC0 or use of the Work. 122 | -------------------------------------------------------------------------------- /source/package-json.d.ts: -------------------------------------------------------------------------------- 1 | import type {LiteralUnion} from './literal-union.d.ts'; 2 | 3 | declare namespace PackageJson { 4 | /** 5 | A person who has been involved in creating or maintaining the package. 6 | */ 7 | export type Person = 8 | | string 9 | | { 10 | name: string; 11 | url?: string; 12 | email?: string; 13 | }; 14 | 15 | export type BugsLocation = 16 | | string 17 | | { 18 | /** 19 | The URL to the package's issue tracker. 20 | */ 21 | url?: string; 22 | 23 | /** 24 | The email address to which issues should be reported. 25 | */ 26 | email?: string; 27 | }; 28 | 29 | export interface DirectoryLocations { 30 | [directoryType: string]: unknown; 31 | 32 | /** 33 | Location for executable scripts. Sugar to generate entries in the `bin` property by walking the folder. 34 | */ 35 | bin?: string; 36 | 37 | /** 38 | Location for Markdown files. 39 | */ 40 | doc?: string; 41 | 42 | /** 43 | Location for example scripts. 44 | */ 45 | example?: string; 46 | 47 | /** 48 | Location for the bulk of the library. 49 | */ 50 | lib?: string; 51 | 52 | /** 53 | Location for man pages. Sugar to generate a `man` array by walking the folder. 54 | */ 55 | man?: string; 56 | 57 | /** 58 | Location for test files. 59 | */ 60 | test?: string; 61 | } 62 | 63 | export type Scripts = { 64 | /** 65 | Run **before** the package is published (Also run on local `npm install` without any arguments). 66 | */ 67 | prepublish?: string; 68 | 69 | /** 70 | Run both **before** the package is packed and published, and on local `npm install` without any arguments. This is run **after** `prepublish`, but **before** `prepublishOnly`. 71 | */ 72 | prepare?: string; 73 | 74 | /** 75 | Run **before** the package is prepared and packed, **only** on `npm publish`. 76 | */ 77 | prepublishOnly?: string; 78 | 79 | /** 80 | Run **before** a tarball is packed (on `npm pack`, `npm publish`, and when installing git dependencies). 81 | */ 82 | prepack?: string; 83 | 84 | /** 85 | Run **after** the tarball has been generated and moved to its final destination. 86 | */ 87 | postpack?: string; 88 | 89 | /** 90 | Run **after** the package is published. 91 | */ 92 | publish?: string; 93 | 94 | /** 95 | Run **after** the package is published. 96 | */ 97 | postpublish?: string; 98 | 99 | /** 100 | Run **before** the package is installed. 101 | */ 102 | preinstall?: string; 103 | 104 | /** 105 | Run **after** the package is installed. 106 | */ 107 | install?: string; 108 | 109 | /** 110 | Run **after** the package is installed and after `install`. 111 | */ 112 | postinstall?: string; 113 | 114 | /** 115 | Run **before** the package is uninstalled and before `uninstall`. 116 | */ 117 | preuninstall?: string; 118 | 119 | /** 120 | Run **before** the package is uninstalled. 121 | */ 122 | uninstall?: string; 123 | 124 | /** 125 | Run **after** the package is uninstalled. 126 | */ 127 | postuninstall?: string; 128 | 129 | /** 130 | Run **before** bump the package version and before `version`. 131 | */ 132 | preversion?: string; 133 | 134 | /** 135 | Run **before** bump the package version. 136 | */ 137 | version?: string; 138 | 139 | /** 140 | Run **after** bump the package version. 141 | */ 142 | postversion?: string; 143 | 144 | /** 145 | Run with the `npm test` command, before `test`. 146 | */ 147 | pretest?: string; 148 | 149 | /** 150 | Run with the `npm test` command. 151 | */ 152 | test?: string; 153 | 154 | /** 155 | Run with the `npm test` command, after `test`. 156 | */ 157 | posttest?: string; 158 | 159 | /** 160 | Run with the `npm stop` command, before `stop`. 161 | */ 162 | prestop?: string; 163 | 164 | /** 165 | Run with the `npm stop` command. 166 | */ 167 | stop?: string; 168 | 169 | /** 170 | Run with the `npm stop` command, after `stop`. 171 | */ 172 | poststop?: string; 173 | 174 | /** 175 | Run with the `npm start` command, before `start`. 176 | */ 177 | prestart?: string; 178 | 179 | /** 180 | Run with the `npm start` command. 181 | */ 182 | start?: string; 183 | 184 | /** 185 | Run with the `npm start` command, after `start`. 186 | */ 187 | poststart?: string; 188 | 189 | /** 190 | Run with the `npm restart` command, before `restart`. Note: `npm restart` will run the `stop` and `start` scripts if no `restart` script is provided. 191 | */ 192 | prerestart?: string; 193 | 194 | /** 195 | Run with the `npm restart` command. Note: `npm restart` will run the `stop` and `start` scripts if no `restart` script is provided. 196 | */ 197 | restart?: string; 198 | 199 | /** 200 | Run with the `npm restart` command, after `restart`. Note: `npm restart` will run the `stop` and `start` scripts if no `restart` script is provided. 201 | */ 202 | postrestart?: string; 203 | } & { 204 | [scriptName: string]: string; 205 | }; 206 | 207 | /** 208 | Dependencies of the package. The version range is a string which has one or more space-separated descriptors. Dependencies can also be identified with a tarball or Git URL. 209 | */ 210 | export interface Dependency { 211 | [packageName: string]: string; 212 | } 213 | 214 | /** 215 | Conditions which provide a way to resolve a package entry point based on the environment. 216 | */ 217 | export type ExportCondition = LiteralUnion< 218 | | 'import' 219 | | 'require' 220 | | 'node' 221 | | 'deno' 222 | | 'browser' 223 | | 'electron' 224 | | 'react-native' 225 | | 'default', 226 | string 227 | >; 228 | 229 | /** 230 | Entry points of a module, optionally with conditions and subpath exports. 231 | */ 232 | export type Exports = 233 | | string 234 | | {[key in ExportCondition]: Exports} 235 | | {[key: string]: Exports}; 236 | 237 | export interface NonStandardEntryPoints { 238 | /** 239 | An ECMAScript module ID that is the primary entry point to the program. 240 | */ 241 | module?: string; 242 | 243 | /** 244 | A module ID with untranspiled code that is the primary entry point to the program. 245 | */ 246 | esnext?: 247 | | string 248 | | { 249 | [moduleName: string]: string | undefined; 250 | main?: string; 251 | browser?: string; 252 | }; 253 | 254 | /** 255 | A hint to JavaScript bundlers or component tools when packaging modules for client side use. 256 | */ 257 | browser?: 258 | | string 259 | | { 260 | [moduleName: string]: string | false; 261 | }; 262 | 263 | /** 264 | Denote which files in your project are "pure" and therefore safe for Webpack to prune if unused. 265 | 266 | [Read more.](https://webpack.js.org/guides/tree-shaking/) 267 | */ 268 | sideEffects?: boolean | string[]; 269 | } 270 | 271 | export interface TypeScriptConfiguration { 272 | /** 273 | Location of the bundled TypeScript declaration file. 274 | */ 275 | types?: string; 276 | 277 | /** 278 | Location of the bundled TypeScript declaration file. Alias of `types`. 279 | */ 280 | typings?: string; 281 | } 282 | 283 | /** 284 | An alternative configuration for Yarn workspaces. 285 | */ 286 | export interface WorkspaceConfig { 287 | /** 288 | An array of workspace pattern strings which contain the workspace packages. 289 | */ 290 | packages?: WorkspacePattern[]; 291 | 292 | /** 293 | Designed to solve the problem of packages which break when their `node_modules` are moved to the root workspace directory - a process known as hoisting. For these packages, both within your workspace, and also some that have been installed via `node_modules`, it is important to have a mechanism for preventing the default Yarn workspace behavior. By adding workspace pattern strings here, Yarn will resume non-workspace behavior for any package which matches the defined patterns. 294 | 295 | [Read more](https://classic.yarnpkg.com/blog/2018/02/15/nohoist/) 296 | */ 297 | nohoist?: WorkspacePattern[]; 298 | } 299 | 300 | /** 301 | A workspace pattern points to a directory or group of directories which contain packages that should be included in the workspace installation process. 302 | 303 | The patterns are handled with [minimatch](https://github.com/isaacs/minimatch). 304 | 305 | @example 306 | `docs` → Include the docs directory and install its dependencies. 307 | `packages/*` → Include all nested directories within the packages directory, like `packages/cli` and `packages/core`. 308 | */ 309 | type WorkspacePattern = string; 310 | 311 | export interface YarnConfiguration { 312 | /** 313 | Used to configure [Yarn workspaces](https://classic.yarnpkg.com/docs/workspaces/). 314 | 315 | Workspaces allow you to manage multiple packages within the same repository in such a way that you only need to run `yarn install` once to install all of them in a single pass. 316 | 317 | Please note that the top-level `private` property of `package.json` **must** be set to `true` in order to use workspaces. 318 | */ 319 | workspaces?: WorkspacePattern[] | WorkspaceConfig; 320 | 321 | /** 322 | If your package only allows one version of a given dependency, and you’d like to enforce the same behavior as `yarn install --flat` on the command-line, set this to `true`. 323 | 324 | Note that if your `package.json` contains `"flat": true` and other packages depend on yours (e.g. you are building a library rather than an app), those other packages will also need `"flat": true` in their `package.json` or be installed with `yarn install --flat` on the command-line. 325 | */ 326 | flat?: boolean; 327 | 328 | /** 329 | Selective version resolutions. Allows the definition of custom package versions inside dependencies without manual edits in the `yarn.lock` file. 330 | */ 331 | resolutions?: Dependency; 332 | } 333 | 334 | export interface JSPMConfiguration { 335 | /** 336 | JSPM configuration. 337 | */ 338 | jspm?: PackageJson; 339 | } 340 | } 341 | 342 | /** 343 | Type for [npm's `package.json` file](https://docs.npmjs.com/creating-a-package-json-file). Also includes types for fields used by other popular projects, like TypeScript and Yarn. 344 | */ 345 | export type PackageJson = { 346 | /** 347 | The name of the package. 348 | */ 349 | name?: string; 350 | 351 | /** 352 | Package version, parseable by [`node-semver`](https://github.com/npm/node-semver). 353 | */ 354 | version?: string; 355 | 356 | /** 357 | Package description, listed in `npm search`. 358 | */ 359 | description?: string; 360 | 361 | /** 362 | Keywords associated with package, listed in `npm search`. 363 | */ 364 | keywords?: string[]; 365 | 366 | /** 367 | The URL to the package's homepage. 368 | */ 369 | homepage?: LiteralUnion<'.', string>; 370 | 371 | /** 372 | The URL to the package's issue tracker and/or the email address to which issues should be reported. 373 | */ 374 | bugs?: PackageJson.BugsLocation; 375 | 376 | /** 377 | The license for the package. 378 | */ 379 | license?: string; 380 | 381 | /** 382 | The licenses for the package. 383 | */ 384 | licenses?: Array<{ 385 | type?: string; 386 | url?: string; 387 | }>; 388 | 389 | author?: PackageJson.Person; 390 | 391 | /** 392 | A list of people who contributed to the package. 393 | */ 394 | contributors?: PackageJson.Person[]; 395 | 396 | /** 397 | A list of people who maintain the package. 398 | */ 399 | maintainers?: PackageJson.Person[]; 400 | 401 | /** 402 | The files included in the package. 403 | */ 404 | files?: string[]; 405 | 406 | /** 407 | Resolution algorithm for importing ".js" files from the package's scope. 408 | 409 | [Read more.](https://nodejs.org/api/esm.html#esm_package_json_type_field) 410 | */ 411 | type?: 'module' | 'commonjs'; 412 | 413 | /** 414 | The module ID that is the primary entry point to the program. 415 | */ 416 | main?: string; 417 | 418 | /** 419 | Standard entry points of the package, with enhanced support for ECMAScript Modules. 420 | 421 | [Read more.](https://nodejs.org/api/esm.html#esm_package_entry_points) 422 | */ 423 | exports?: PackageJson.Exports; 424 | 425 | /** 426 | The executable files that should be installed into the `PATH`. 427 | */ 428 | bin?: 429 | | string 430 | | { 431 | [binary: string]: string; 432 | }; 433 | 434 | /** 435 | Filenames to put in place for the `man` program to find. 436 | */ 437 | man?: string | string[]; 438 | 439 | /** 440 | Indicates the structure of the package. 441 | */ 442 | directories?: PackageJson.DirectoryLocations; 443 | 444 | /** 445 | Location for the code repository. 446 | */ 447 | repository?: 448 | | string 449 | | { 450 | type: string; 451 | url: string; 452 | 453 | /** 454 | Relative path to package.json if it is placed in non-root directory (for example if it is part of a monorepo). 455 | 456 | [Read more.](https://github.com/npm/rfcs/blob/latest/implemented/0010-monorepo-subdirectory-declaration.md) 457 | */ 458 | directory?: string; 459 | }; 460 | 461 | /** 462 | Script commands that are run at various times in the lifecycle of the package. The key is the lifecycle event, and the value is the command to run at that point. 463 | */ 464 | scripts?: PackageJson.Scripts; 465 | 466 | /** 467 | Is used to set configuration parameters used in package scripts that persist across upgrades. 468 | */ 469 | config?: { 470 | [configKey: string]: unknown; 471 | }; 472 | 473 | /** 474 | The dependencies of the package. 475 | */ 476 | dependencies?: PackageJson.Dependency; 477 | 478 | /** 479 | Additional tooling dependencies that are not required for the package to work. Usually test, build, or documentation tooling. 480 | */ 481 | devDependencies?: PackageJson.Dependency; 482 | 483 | /** 484 | Dependencies that are skipped if they fail to install. 485 | */ 486 | optionalDependencies?: PackageJson.Dependency; 487 | 488 | /** 489 | Dependencies that will usually be required by the package user directly or via another dependency. 490 | */ 491 | peerDependencies?: PackageJson.Dependency; 492 | 493 | /** 494 | Indicate peer dependencies that are optional. 495 | */ 496 | peerDependenciesMeta?: { 497 | [packageName: string]: { 498 | optional: true; 499 | }; 500 | }; 501 | 502 | /** 503 | Package names that are bundled when the package is published. 504 | */ 505 | bundledDependencies?: string[]; 506 | 507 | /** 508 | Alias of `bundledDependencies`. 509 | */ 510 | bundleDependencies?: string[]; 511 | 512 | /** 513 | Engines that this package runs on. 514 | */ 515 | engines?: { 516 | [EngineName in 'npm' | 'node' | string]: string; 517 | }; 518 | 519 | /** 520 | @deprecated 521 | */ 522 | engineStrict?: boolean; 523 | 524 | /** 525 | Operating systems the module runs on. 526 | */ 527 | os?: Array>; 544 | 545 | /** 546 | CPU architectures the module runs on. 547 | */ 548 | cpu?: Array>; 573 | 574 | /** 575 | If set to `true`, a warning will be shown if package is installed locally. Useful if the package is primarily a command-line application that should be installed globally. 576 | 577 | @deprecated 578 | */ 579 | preferGlobal?: boolean; 580 | 581 | /** 582 | If set to `true`, then npm will refuse to publish it. 583 | */ 584 | private?: boolean; 585 | 586 | /** 587 | A set of config values that will be used at publish-time. It's especially handy to set the tag, registry or access, to ensure that a given package is not tagged with 'latest', published to the global public registry or that a scoped module is private by default. 588 | */ 589 | publishConfig?: { 590 | [config: string]: unknown; 591 | }; 592 | 593 | /** 594 | Describes and notifies consumers of a package's monetary support information. 595 | 596 | [Read more.](https://github.com/npm/rfcs/blob/latest/accepted/0017-add-funding-support.md) 597 | */ 598 | funding?: string | { 599 | /** 600 | The type of funding. 601 | */ 602 | type?: LiteralUnion< 603 | | 'github' 604 | | 'opencollective' 605 | | 'patreon' 606 | | 'individual' 607 | | 'foundation' 608 | | 'corporation', 609 | string 610 | >; 611 | /** 612 | The URL to the funding page. 613 | */ 614 | url: string; 615 | }; 616 | } & 617 | PackageJson.NonStandardEntryPoints & 618 | PackageJson.TypeScriptConfiguration & 619 | PackageJson.YarnConfiguration & 620 | PackageJson.JSPMConfiguration & { 621 | [key: string]: unknown; 622 | }; 623 | -------------------------------------------------------------------------------- /source/tsconfig-json.d.ts: -------------------------------------------------------------------------------- 1 | declare namespace TsConfigJson { 2 | namespace CompilerOptions { 3 | export type JSX = 4 | | 'preserve' 5 | | 'react' 6 | | 'react-native'; 7 | 8 | export type Module = 9 | | 'CommonJS' 10 | | 'AMD' 11 | | 'System' 12 | | 'UMD' 13 | | 'ES6' 14 | | 'ES2015' 15 | | 'ESNext' 16 | | 'None' 17 | // Lowercase alternatives 18 | | 'commonjs' 19 | | 'amd' 20 | | 'system' 21 | | 'umd' 22 | | 'es6' 23 | | 'es2015' 24 | | 'esnext' 25 | | 'none'; 26 | 27 | export type NewLine = 28 | | 'CRLF' 29 | | 'LF' 30 | // Lowercase alternatives 31 | | 'crlf' 32 | | 'lf'; 33 | 34 | export type Target = 35 | | 'ES3' 36 | | 'ES5' 37 | | 'ES6' 38 | | 'ES2015' 39 | | 'ES2016' 40 | | 'ES2017' 41 | | 'ES2018' 42 | | 'ES2019' 43 | | 'ES2020' 44 | | 'ESNext' 45 | // Lowercase alternatives 46 | | 'es3' 47 | | 'es5' 48 | | 'es6' 49 | | 'es2015' 50 | | 'es2016' 51 | | 'es2017' 52 | | 'es2018' 53 | | 'es2019' 54 | | 'es2020' 55 | | 'esnext'; 56 | 57 | export type Lib = 58 | | 'ES5' 59 | | 'ES6' 60 | | 'ES7' 61 | | 'ES2015' 62 | | 'ES2015.Collection' 63 | | 'ES2015.Core' 64 | | 'ES2015.Generator' 65 | | 'ES2015.Iterable' 66 | | 'ES2015.Promise' 67 | | 'ES2015.Proxy' 68 | | 'ES2015.Reflect' 69 | | 'ES2015.Symbol.WellKnown' 70 | | 'ES2015.Symbol' 71 | | 'ES2016' 72 | | 'ES2016.Array.Include' 73 | | 'ES2017' 74 | | 'ES2017.Intl' 75 | | 'ES2017.Object' 76 | | 'ES2017.SharedMemory' 77 | | 'ES2017.String' 78 | | 'ES2017.TypedArrays' 79 | | 'ES2018' 80 | | 'ES2018.AsyncIterable' 81 | | 'ES2018.Intl' 82 | | 'ES2018.Promise' 83 | | 'ES2018.Regexp' 84 | | 'ES2019' 85 | | 'ES2019.Array' 86 | | 'ES2019.Object' 87 | | 'ES2019.String' 88 | | 'ES2019.Symbol' 89 | | 'ES2020' 90 | | 'ES2020.String' 91 | | 'ES2020.Symbol.WellKnown' 92 | | 'ESNext' 93 | | 'ESNext.Array' 94 | | 'ESNext.AsyncIterable' 95 | | 'ESNext.BigInt' 96 | | 'ESNext.Intl' 97 | | 'ESNext.Symbol' 98 | | 'DOM' 99 | | 'DOM.Iterable' 100 | | 'ScriptHost' 101 | | 'WebWorker' 102 | | 'WebWorker.ImportScripts' 103 | // Lowercase alternatives 104 | | 'es5' 105 | | 'es6' 106 | | 'es7' 107 | | 'es2015' 108 | | 'es2015.collection' 109 | | 'es2015.core' 110 | | 'es2015.generator' 111 | | 'es2015.iterable' 112 | | 'es2015.promise' 113 | | 'es2015.proxy' 114 | | 'es2015.reflect' 115 | | 'es2015.symbol.wellknown' 116 | | 'es2015.symbol' 117 | | 'es2016' 118 | | 'es2016.array.include' 119 | | 'es2017' 120 | | 'es2017.intl' 121 | | 'es2017.object' 122 | | 'es2017.sharedmemory' 123 | | 'es2017.string' 124 | | 'es2017.typedarrays' 125 | | 'es2018' 126 | | 'es2018.asynciterable' 127 | | 'es2018.intl' 128 | | 'es2018.promise' 129 | | 'es2018.regexp' 130 | | 'es2019' 131 | | 'es2019.array' 132 | | 'es2019.object' 133 | | 'es2019.string' 134 | | 'es2019.symbol' 135 | | 'es2020' 136 | | 'es2020.string' 137 | | 'es2020.symbol.wellknown' 138 | | 'esnext' 139 | | 'esnext.array' 140 | | 'esnext.asynciterable' 141 | | 'esnext.bigint' 142 | | 'esnext.intl' 143 | | 'esnext.symbol' 144 | | 'dom' 145 | | 'dom.iterable' 146 | | 'scripthost' 147 | | 'webworker' 148 | | 'webworker.importscripts'; 149 | 150 | export interface Plugin { 151 | [key: string]: unknown; 152 | /** 153 | Plugin name. 154 | */ 155 | name?: string; 156 | } 157 | } 158 | 159 | export interface CompilerOptions { 160 | /** 161 | The character set of the input files. 162 | 163 | @default 'utf8' 164 | */ 165 | charset?: string; 166 | 167 | /** 168 | Enables building for project references. 169 | 170 | @default true 171 | */ 172 | composite?: boolean; 173 | 174 | /** 175 | Generates corresponding d.ts files. 176 | 177 | @default false 178 | */ 179 | declaration?: boolean; 180 | 181 | /** 182 | Specify output directory for generated declaration files. 183 | 184 | Requires TypeScript version 2.0 or later. 185 | */ 186 | declarationDir?: string; 187 | 188 | /** 189 | Show diagnostic information. 190 | 191 | @default false 192 | */ 193 | diagnostics?: boolean; 194 | 195 | /** 196 | Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. 197 | 198 | @default false 199 | */ 200 | emitBOM?: boolean; 201 | 202 | /** 203 | Only emit `.d.ts` declaration files. 204 | 205 | @default false 206 | */ 207 | emitDeclarationOnly?: boolean; 208 | 209 | /** 210 | Enable incremental compilation. 211 | 212 | @default `composite` 213 | */ 214 | incremental?: boolean; 215 | 216 | /** 217 | Specify file to store incremental compilation information. 218 | 219 | @default '.tsbuildinfo' 220 | */ 221 | tsBuildInfoFile?: string; 222 | 223 | /** 224 | Emit a single file with source maps instead of having a separate file. 225 | 226 | @default false 227 | */ 228 | inlineSourceMap?: boolean; 229 | 230 | /** 231 | Emit the source alongside the sourcemaps within a single file. 232 | 233 | Requires `--inlineSourceMap` to be set. 234 | 235 | @default false 236 | */ 237 | inlineSources?: boolean; 238 | 239 | /** 240 | Specify JSX code generation: `'preserve'`, `'react'`, or `'react-native'`. 241 | 242 | @default 'preserve' 243 | */ 244 | jsx?: CompilerOptions.JSX; 245 | 246 | /** 247 | Specifies the object invoked for `createElement` and `__spread` when targeting `'react'` JSX emit. 248 | 249 | @default 'React' 250 | */ 251 | reactNamespace?: string; 252 | 253 | /** 254 | Print names of files part of the compilation. 255 | 256 | @default false 257 | */ 258 | listFiles?: boolean; 259 | 260 | /** 261 | Specifies the location where debugger should locate map files instead of generated locations. 262 | */ 263 | mapRoot?: string; 264 | 265 | /** 266 | Specify module code generation: 'None', 'CommonJS', 'AMD', 'System', 'UMD', 'ES6', 'ES2015' or 'ESNext'. Only 'AMD' and 'System' can be used in conjunction with `--outFile`. 'ES6' and 'ES2015' values may be used when targeting 'ES5' or lower. 267 | 268 | @default ['ES3', 'ES5'].includes(target) ? 'CommonJS' : 'ES6' 269 | */ 270 | module?: CompilerOptions.Module; 271 | 272 | /** 273 | Specifies the end of line sequence to be used when emitting files: 'crlf' (Windows) or 'lf' (Unix). 274 | 275 | Default: Platform specific 276 | */ 277 | newLine?: CompilerOptions.NewLine; 278 | 279 | /** 280 | Do not emit output. 281 | 282 | @default false 283 | */ 284 | noEmit?: boolean; 285 | 286 | /** 287 | Do not generate custom helper functions like `__extends` in compiled output. 288 | 289 | @default false 290 | */ 291 | noEmitHelpers?: boolean; 292 | 293 | /** 294 | Do not emit outputs if any type checking errors were reported. 295 | 296 | @default false 297 | */ 298 | noEmitOnError?: boolean; 299 | 300 | /** 301 | Warn on expressions and declarations with an implied 'any' type. 302 | 303 | @default false 304 | */ 305 | noImplicitAny?: boolean; 306 | 307 | /** 308 | Raise error on 'this' expressions with an implied any type. 309 | 310 | @default false 311 | */ 312 | noImplicitThis?: boolean; 313 | 314 | /** 315 | Report errors on unused locals. 316 | 317 | Requires TypeScript version 2.0 or later. 318 | 319 | @default false 320 | */ 321 | noUnusedLocals?: boolean; 322 | 323 | /** 324 | Report errors on unused parameters. 325 | 326 | Requires TypeScript version 2.0 or later. 327 | 328 | @default false 329 | */ 330 | noUnusedParameters?: boolean; 331 | 332 | /** 333 | Do not include the default library file (lib.d.ts). 334 | 335 | @default false 336 | */ 337 | noLib?: boolean; 338 | 339 | /** 340 | Do not add triple-slash references or module import targets to the list of compiled files. 341 | 342 | @default false 343 | */ 344 | noResolve?: boolean; 345 | 346 | /** 347 | Disable strict checking of generic signatures in function types. 348 | 349 | @default false 350 | */ 351 | noStrictGenericChecks?: boolean; 352 | 353 | /** 354 | @deprecated use `skipLibCheck` instead. 355 | */ 356 | skipDefaultLibCheck?: boolean; 357 | 358 | /** 359 | Skip type checking of declaration files. 360 | 361 | Requires TypeScript version 2.0 or later. 362 | 363 | @default false 364 | */ 365 | skipLibCheck?: boolean; 366 | 367 | /** 368 | Concatenate and emit output to single file. 369 | */ 370 | outFile?: string; 371 | 372 | /** 373 | Redirect output structure to the directory. 374 | */ 375 | outDir?: string; 376 | 377 | /** 378 | Do not erase const enum declarations in generated code. 379 | 380 | @default false 381 | */ 382 | preserveConstEnums?: boolean; 383 | 384 | /** 385 | Do not resolve symlinks to their real path; treat a symlinked file like a real one. 386 | 387 | @default false 388 | */ 389 | preserveSymlinks?: boolean; 390 | 391 | /** 392 | Keep outdated console output in watch mode instead of clearing the screen. 393 | 394 | @default false 395 | */ 396 | preserveWatchOutput?: boolean; 397 | 398 | /** 399 | Stylize errors and messages using color and context (experimental). 400 | 401 | @default true // Unless piping to another program or redirecting output to a file. 402 | */ 403 | pretty?: boolean; 404 | 405 | /** 406 | Do not emit comments to output. 407 | 408 | @default false 409 | */ 410 | removeComments?: boolean; 411 | 412 | /** 413 | Specifies the root directory of input files. 414 | 415 | Use to control the output directory structure with `--outDir`. 416 | */ 417 | rootDir?: string; 418 | 419 | /** 420 | Unconditionally emit imports for unresolved files. 421 | 422 | @default false 423 | */ 424 | isolatedModules?: boolean; 425 | 426 | /** 427 | Generates corresponding '.map' file. 428 | 429 | @default false 430 | */ 431 | sourceMap?: boolean; 432 | 433 | /** 434 | Specifies the location where debugger should locate TypeScript files instead of source locations. 435 | */ 436 | sourceRoot?: string; 437 | 438 | /** 439 | Suppress excess property checks for object literals. 440 | 441 | @default false 442 | */ 443 | suppressExcessPropertyErrors?: boolean; 444 | 445 | /** 446 | Suppress noImplicitAny errors for indexing objects lacking index signatures. 447 | 448 | @default false 449 | */ 450 | suppressImplicitAnyIndexErrors?: boolean; 451 | 452 | /** 453 | Do not emit declarations for code that has an `@internal` annotation. 454 | */ 455 | stripInternal?: boolean; 456 | 457 | /** 458 | Specify ECMAScript target version. 459 | 460 | @default 'es3' 461 | */ 462 | target?: CompilerOptions.Target; 463 | 464 | /** 465 | Watch input files. 466 | 467 | @default false 468 | */ 469 | watch?: boolean; 470 | 471 | /** 472 | Enables experimental support for ES7 decorators. 473 | 474 | @default false 475 | */ 476 | experimentalDecorators?: boolean; 477 | 478 | /** 479 | Emit design-type metadata for decorated declarations in source. 480 | 481 | @default false 482 | */ 483 | emitDecoratorMetadata?: boolean; 484 | 485 | /** 486 | Specifies module resolution strategy: 'node' (Node) or 'classic' (TypeScript pre 1.6). 487 | 488 | @default ['AMD', 'System', 'ES6'].includes(module) ? 'classic' : 'node' 489 | */ 490 | moduleResolution?: 'classic' | 'node'; 491 | 492 | /** 493 | Do not report errors on unused labels. 494 | 495 | @default false 496 | */ 497 | allowUnusedLabels?: boolean; 498 | 499 | /** 500 | Report error when not all code paths in function return a value. 501 | 502 | @default false 503 | */ 504 | noImplicitReturns?: boolean; 505 | 506 | /** 507 | Report errors for fallthrough cases in switch statement. 508 | 509 | @default false 510 | */ 511 | noFallthroughCasesInSwitch?: boolean; 512 | 513 | /** 514 | Do not report errors on unreachable code. 515 | 516 | @default false 517 | */ 518 | allowUnreachableCode?: boolean; 519 | 520 | /** 521 | Disallow inconsistently-cased references to the same file. 522 | 523 | @default false 524 | */ 525 | forceConsistentCasingInFileNames?: boolean; 526 | 527 | /** 528 | Base directory to resolve non-relative module names. 529 | */ 530 | baseUrl?: string; 531 | 532 | /** 533 | Specify path mapping to be computed relative to baseUrl option. 534 | */ 535 | paths?: { 536 | [key: string]: string[]; 537 | }; 538 | 539 | /** 540 | List of TypeScript language server plugins to load. 541 | 542 | Requires TypeScript version 2.3 or later. 543 | */ 544 | plugins?: CompilerOptions.Plugin[]; 545 | 546 | /** 547 | Specify list of root directories to be used when resolving modules. 548 | */ 549 | rootDirs?: string[]; 550 | 551 | /** 552 | Specify list of directories for type definition files to be included. 553 | 554 | Requires TypeScript version 2.0 or later. 555 | */ 556 | typeRoots?: string[]; 557 | 558 | /** 559 | Type declaration files to be included in compilation. 560 | 561 | Requires TypeScript version 2.0 or later. 562 | */ 563 | types?: string[]; 564 | 565 | /** 566 | Enable tracing of the name resolution process. 567 | 568 | @default false 569 | */ 570 | traceResolution?: boolean; 571 | 572 | /** 573 | Allow javascript files to be compiled. 574 | 575 | @default false 576 | */ 577 | allowJs?: boolean; 578 | 579 | /** 580 | Do not truncate error messages. 581 | 582 | @default false 583 | */ 584 | noErrorTruncation?: boolean; 585 | 586 | /** 587 | Allow default imports from modules with no default export. This does not affect code emit, just typechecking. 588 | 589 | @default module === 'system' || esModuleInterop 590 | */ 591 | allowSyntheticDefaultImports?: boolean; 592 | 593 | /** 594 | Do not emit `'use strict'` directives in module output. 595 | 596 | @default false 597 | */ 598 | noImplicitUseStrict?: boolean; 599 | 600 | /** 601 | Enable to list all emitted files. 602 | 603 | Requires TypeScript version 2.0 or later. 604 | 605 | @default false 606 | */ 607 | listEmittedFiles?: boolean; 608 | 609 | /** 610 | Disable size limit for JavaScript project. 611 | 612 | Requires TypeScript version 2.0 or later. 613 | 614 | @default false 615 | */ 616 | disableSizeLimit?: boolean; 617 | 618 | /** 619 | List of library files to be included in the compilation. 620 | 621 | Requires TypeScript version 2.0 or later. 622 | */ 623 | lib?: CompilerOptions.Lib[]; 624 | 625 | /** 626 | Enable strict null checks. 627 | 628 | Requires TypeScript version 2.0 or later. 629 | 630 | @default false 631 | */ 632 | strictNullChecks?: boolean; 633 | 634 | /** 635 | The maximum dependency depth to search under `node_modules` and load JavaScript files. Only applicable with `--allowJs`. 636 | 637 | @default 0 638 | */ 639 | maxNodeModuleJsDepth?: number; 640 | 641 | /** 642 | Import emit helpers (e.g. `__extends`, `__rest`, etc..) from tslib. 643 | 644 | Requires TypeScript version 2.1 or later. 645 | 646 | @default false 647 | */ 648 | importHelpers?: boolean; 649 | 650 | /** 651 | Specify the JSX factory function to use when targeting React JSX emit, e.g. `React.createElement` or `h`. 652 | 653 | Requires TypeScript version 2.1 or later. 654 | 655 | @default 'React.createElement' 656 | */ 657 | jsxFactory?: string; 658 | 659 | /** 660 | Parse in strict mode and emit `'use strict'` for each source file. 661 | 662 | Requires TypeScript version 2.1 or later. 663 | 664 | @default false 665 | */ 666 | alwaysStrict?: boolean; 667 | 668 | /** 669 | Enable all strict type checking options. 670 | 671 | Requires TypeScript version 2.3 or later. 672 | 673 | @default false 674 | */ 675 | strict?: boolean; 676 | 677 | /** 678 | Enable stricter checking of of the `bind`, `call`, and `apply` methods on functions. 679 | 680 | @default false 681 | */ 682 | strictBindCallApply?: boolean; 683 | 684 | /** 685 | Provide full support for iterables in `for-of`, spread, and destructuring when targeting `ES5` or `ES3`. 686 | 687 | Requires TypeScript version 2.3 or later. 688 | 689 | @default false 690 | */ 691 | downlevelIteration?: boolean; 692 | 693 | /** 694 | Report errors in `.js` files. 695 | 696 | Requires TypeScript version 2.3 or later. 697 | 698 | @default false 699 | */ 700 | checkJs?: boolean; 701 | 702 | /** 703 | Disable bivariant parameter checking for function types. 704 | 705 | Requires TypeScript version 2.6 or later. 706 | 707 | @default false 708 | */ 709 | strictFunctionTypes?: boolean; 710 | 711 | /** 712 | Ensure non-undefined class properties are initialized in the constructor. 713 | 714 | Requires TypeScript version 2.7 or later. 715 | 716 | @default false 717 | */ 718 | strictPropertyInitialization?: boolean; 719 | 720 | /** 721 | Emit `__importStar` and `__importDefault` helpers for runtime Babel ecosystem compatibility and enable `--allowSyntheticDefaultImports` for typesystem compatibility. 722 | 723 | Requires TypeScript version 2.7 or later. 724 | 725 | @default false 726 | */ 727 | esModuleInterop?: boolean; 728 | 729 | /** 730 | Allow accessing UMD globals from modules. 731 | 732 | @default false 733 | */ 734 | allowUmdGlobalAccess?: boolean; 735 | 736 | /** 737 | Resolve `keyof` to string valued property names only (no numbers or symbols). 738 | 739 | Requires TypeScript version 2.9 or later. 740 | 741 | @default false 742 | */ 743 | keyofStringsOnly?: boolean; 744 | 745 | /** 746 | Emit ECMAScript standard class fields. 747 | 748 | Requires TypeScript version 3.7 or later. 749 | 750 | @default false 751 | */ 752 | useDefineForClassFields?: boolean; 753 | 754 | /** 755 | Generates a sourcemap for each corresponding `.d.ts` file. 756 | 757 | Requires TypeScript version 2.9 or later. 758 | 759 | @default false 760 | */ 761 | declarationMap?: boolean; 762 | 763 | /** 764 | Include modules imported with `.json` extension. 765 | 766 | Requires TypeScript version 2.9 or later. 767 | 768 | @default false 769 | */ 770 | resolveJsonModule?: boolean; 771 | } 772 | 773 | /** 774 | Auto type (.d.ts) acquisition options for this project. 775 | 776 | Requires TypeScript version 2.1 or later. 777 | */ 778 | export interface TypeAcquisition { 779 | /** 780 | Enable auto type acquisition. 781 | */ 782 | enable?: boolean; 783 | 784 | /** 785 | Specifies a list of type declarations to be included in auto type acquisition. For example, `['jquery', 'lodash']`. 786 | */ 787 | include?: string[]; 788 | 789 | /** 790 | Specifies a list of type declarations to be excluded from auto type acquisition. For example, `['jquery', 'lodash']`. 791 | */ 792 | exclude?: string[]; 793 | } 794 | 795 | export interface References { 796 | /** 797 | A normalized path on disk. 798 | */ 799 | path: string; 800 | 801 | /** 802 | The path as the user originally wrote it. 803 | */ 804 | originalPath?: string; 805 | 806 | /** 807 | True if the output of this reference should be prepended to the output of this project. 808 | 809 | Only valid for `--outFile` compilations. 810 | */ 811 | prepend?: boolean; 812 | 813 | /** 814 | True if it is intended that this reference form a circularity. 815 | */ 816 | circular?: boolean; 817 | } 818 | } 819 | 820 | export interface TsConfigJson { 821 | /** 822 | Instructs the TypeScript compiler how to compile `.ts` files. 823 | */ 824 | compilerOptions?: TsConfigJson.CompilerOptions; 825 | 826 | /** 827 | Auto type (.d.ts) acquisition options for this project. 828 | 829 | Requires TypeScript version 2.1 or later. 830 | */ 831 | typeAcquisition?: TsConfigJson.TypeAcquisition; 832 | 833 | /** 834 | Enable Compile-on-Save for this project. 835 | */ 836 | compileOnSave?: boolean; 837 | 838 | /** 839 | Path to base configuration file to inherit from. 840 | 841 | Requires TypeScript version 2.1 or later. 842 | */ 843 | extends?: string; 844 | 845 | /** 846 | If no `files` or `include` property is present in a `tsconfig.json`, the compiler defaults to including all files in the containing directory and subdirectories except those specified by `exclude`. When a `files` property is specified, only those files and those specified by `include` are included. 847 | */ 848 | files?: string[]; 849 | 850 | /** 851 | Specifies a list of files to be excluded from compilation. The `exclude` property only affects the files included via the `include` property and not the `files` property. 852 | 853 | Glob patterns require TypeScript version 2.0 or later. 854 | */ 855 | exclude?: string[]; 856 | 857 | /** 858 | Specifies a list of glob patterns that match files to be included in compilation. 859 | 860 | If no `files` or `include` property is present in a `tsconfig.json`, the compiler defaults to including all files in the containing directory and subdirectories except those specified by `exclude`. 861 | 862 | Requires TypeScript version 2.0 or later. 863 | */ 864 | include?: string[]; 865 | 866 | /** 867 | Referenced projects. 868 | 869 | Requires TypeScript version 3.0 or later. 870 | */ 871 | references?: TsConfigJson.References[]; 872 | } 873 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 | type-fest 5 |
6 |
7 | A collection of essential TypeScript types 8 |
9 |
10 |
11 |
12 |
13 | 14 | [![Build Status](https://travis-ci.com/sindresorhus/type-fest.svg?branch=master)](https://travis-ci.com/sindresorhus/type-fest) 15 | [![](https://img.shields.io/badge/unicorn-approved-ff69b4.svg)](https://giphy.com/gifs/illustration-rainbow-unicorn-26AHG5KGFxSkUWw1i) 16 | 19 | 20 | **NOTE: this is a maintained fork for Deno of the [original](https://github.com/sindresorhus/type-fest)! Go support [sindresorhus](https://github.com/sindresorhus) for creating this project!** 21 | 22 | ## Deno Example 23 | ```ts 24 | import type {Except} from 'https://cdn.jsdelivr.net/gh/denofn/type-fest@latest/mod.ts'; 25 | 26 | type Foo = { 27 | unicorn: string; 28 | rainbow: boolean; 29 | }; 30 | 31 | type FooWithoutRainbow = Except; 32 | //=> {unicorn: string} 33 | ``` 34 | 35 | Many of the types here should have been built-in. You can help by suggesting some of them to the [TypeScript project](https://github.com/Microsoft/TypeScript/blob/master/CONTRIBUTING.md). 36 | 37 | Either add this package as a dependency or copy-paste the needed types. No credit required. 👌 38 | 39 | PR welcome for additional commonly needed types and docs improvements. Read the [contributing guidelines](.github/contributing.md) first. 40 | 41 | ## Install 42 | 43 | ``` 44 | $ npm install type-fest 45 | ``` 46 | 47 | *Requires TypeScript >=3.2* 48 | 49 | ## Usage 50 | 51 | ```ts 52 | import {Except} from 'type-fest'; 53 | 54 | type Foo = { 55 | unicorn: string; 56 | rainbow: boolean; 57 | }; 58 | 59 | type FooWithoutRainbow = Except; 60 | //=> {unicorn: string} 61 | ``` 62 | 63 | ## API 64 | 65 | Click the type names for complete docs. 66 | 67 | ### Basic 68 | 69 | - [`Primitive`](source/basic.d.ts) - Matches any [primitive value](https://developer.mozilla.org/en-US/docs/Glossary/Primitive). 70 | - [`Class`](source/basic.d.ts) - Matches a [`class` constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes). 71 | - [`TypedArray`](source/basic.d.ts) - Matches any [typed array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray), like `Uint8Array` or `Float64Array`. 72 | - [`JsonObject`](source/basic.d.ts) - Matches a JSON object. 73 | - [`JsonArray`](source/basic.d.ts) - Matches a JSON array. 74 | - [`JsonValue`](source/basic.d.ts) - Matches any valid JSON value. 75 | - [`ObservableLike`](source/basic.d.ts) - Matches a value that is like an [Observable](https://github.com/tc39/proposal-observable). 76 | 77 | ### Utilities 78 | 79 | - [`Except`](source/except.d.ts) - Create a type from an object type without certain keys. This is a stricter version of [`Omit`](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-5.html#the-omit-helper-type). 80 | - [`Mutable`](source/mutable.d.ts) - Convert an object with `readonly` keys into a mutable object. The inverse of `Readonly`. 81 | - [`Merge`](source/merge.d.ts) - Merge two types into a new type. Keys of the second type overrides keys of the first type. 82 | - [`MergeExclusive`](source/merge-exclusive.d.ts) - Create a type that has mutually exclusive keys. 83 | - [`RequireAtLeastOne`](source/require-at-least-one.d.ts) - Create a type that requires at least one of the given keys. 84 | - [`RequireExactlyOne`](source/require-exactly-one.d.ts) - Create a type that requires exactly a single key of the given keys and disallows more. 85 | - [`PartialDeep`](source/partial-deep.d.ts) - Create a deeply optional version of another type. Use [`Partial`](https://github.com/Microsoft/TypeScript/blob/2961bc3fc0ea1117d4e53bc8e97fa76119bc33e3/src/lib/es5.d.ts#L1401-L1406) if you only need one level deep. 86 | - [`ReadonlyDeep`](source/readonly-deep.d.ts) - Create a deeply immutable version of an `object`/`Map`/`Set`/`Array` type. Use [`Readonly`](https://github.com/Microsoft/TypeScript/blob/2961bc3fc0ea1117d4e53bc8e97fa76119bc33e3/src/lib/es5.d.ts#L1415-L1420) if you only need one level deep. 87 | - [`LiteralUnion`](source/literal-union.d.ts) - Create a union type by combining primitive types and literal types without sacrificing auto-completion in IDEs for the literal type part of the union. Workaround for [Microsoft/TypeScript#29729](https://github.com/Microsoft/TypeScript/issues/29729). 88 | - [`Promisable`](source/promisable.d.ts) - Create a type that represents either the value or the value wrapped in `PromiseLike`. 89 | - [`Opaque`](source/opaque.d.ts) - Create an [opaque type](https://codemix.com/opaque-types-in-javascript/). 90 | - [`SetOptional`](source/set-optional.d.ts) - Create a type that makes the given keys optional. 91 | - [`SetRequired`](source/set-required.d.ts) - Create a type that makes the given keys required. 92 | - [`ValueOf`](source/value-of.d.ts) - Create a union of the given object's values, and optionally specify which keys to get the values from. 93 | - [`PromiseValue`](source/promise-value.d.ts) - Returns the type that is wrapped inside a `Promise`. 94 | - [`AsyncReturnType`](source/async-return-type.d.ts) - Unwrap the return type of a function that returns a `Promise`. 95 | - [`ConditionalKeys`](source/conditional-keys.d.ts) - Extract keys from a shape where values extend the given `Condition` type. 96 | - [`ConditionalPick`](source/conditional-pick.d.ts) - Like `Pick` except it selects properties from a shape where the values extend the given `Condition` type. 97 | - [`ConditionalExcept`](source/conditional-except.d.ts) - Like `Omit` except it removes properties from a shape where the values extend the given `Condition` type. 98 | - [`UnionToIntersection`](source/union-to-intersection.d.ts) - Convert a union type to an intersection type. 99 | - [`Stringified`](source/stringified.d.ts) - Create a type with the keys of the given type changed to `string` type. 100 | - [`FixedLengthArray`](source/fixed-length-array.d.ts) - Create a type that represents an array of the given type and length. 101 | 102 | ### Miscellaneous 103 | 104 | - [`PackageJson`](source/package-json.d.ts) - Type for [npm's `package.json` file](https://docs.npmjs.com/creating-a-package-json-file). 105 | - [`TsConfigJson`](source/tsconfig-json.d.ts) - Type for [TypeScript's `tsconfig.json` file](https://www.typescriptlang.org/docs/handbook/tsconfig-json.html) (TypeScript 3.7). 106 | 107 | ## Declined types 108 | 109 | *If we decline a type addition, we will make sure to document the better solution here.* 110 | 111 | - [`Diff` and `Spread`](https://github.com/sindresorhus/type-fest/pull/7) - The PR author didn't provide any real-world use-cases and the PR went stale. If you think this type is useful, provide some real-world use-cases and we might reconsider. 112 | - [`Dictionary`](https://github.com/sindresorhus/type-fest/issues/33) - You only save a few characters (`Dictionary` vs `Record`) from [`Record`](https://github.com/Microsoft/TypeScript/blob/2961bc3fc0ea1117d4e53bc8e97fa76119bc33e3/src/lib/es5.d.ts#L1429-L1434), which is more flexible and well-known. Also, you shouldn't use an object as a dictionary. We have `Map` in JavaScript now. 113 | - [`SubType`](https://github.com/sindresorhus/type-fest/issues/22) - The type is powerful, but lacks good use-cases and is prone to misuse. 114 | - [`ExtractProperties` and `ExtractMethods`](https://github.com/sindresorhus/type-fest/pull/4) - The types violate the single responsibility principle. Instead, refine your types into more granular type hierarchies. 115 | 116 | ## Tips 117 | 118 | ### Built-in types 119 | 120 | There are many advanced types most users don't know about. 121 | 122 | - [`Partial`](https://github.com/Microsoft/TypeScript/blob/2961bc3fc0ea1117d4e53bc8e97fa76119bc33e3/src/lib/es5.d.ts#L1401-L1406) - Make all properties in `T` optional. 123 |
124 | 125 | Example 126 | 127 | 128 | [Playground](https://www.typescriptlang.org/play/#code/JYOwLgpgTgZghgYwgAgHIHsAmEDC6QzADmyA3gLABQyycADnanALYQBcyAzmFKEQNxUaddFDAcQAV2YAjaIMoBfKlQQAbOJ05osEAIIMAQpOBrsUMkOR1eANziRkCfISKSoD4Pg4ZseAsTIALyW1DS0DEysHADkvvoMMQA0VsKi4sgAzAAMuVaKClY2wPaOknSYDrguADwA0sgQAB6QIJjaANYQAJ7oMDp+LsQAfAAUXd0cdUnI9mo+uv6uANp1ALoAlKHhyGAAFsCcAHTOAW4eYF4gyxNrwbNwago0ypRWp66jH8QcAApwYmAjxq8SWIy2FDCNDA3ToKFBQyIdR69wmfQG1TOhShyBgomQX3w3GQE2Q6IA8jIAFYQBBgI4TTiEs5bTQYsFInrLTbbHZOIlgZDlSqQABqj0kKBC3yINx6a2xfOQwH6o2FVXFaklwSCIUkbQghBAEEwENSfNOlykEGefNe5uhB2O6sgS3GPRmLogmslG1tLxUOKgEDA7hAuydtteryAA) 129 | 130 | ```ts 131 | interface NodeConfig { 132 | appName: string; 133 | port: number; 134 | } 135 | 136 | class NodeAppBuilder { 137 | private configuration: NodeConfig = { 138 | appName: 'NodeApp', 139 | port: 3000 140 | }; 141 | 142 | private updateConfig(key: Key, value: NodeConfig[Key]) { 143 | this.configuration[key] = value; 144 | } 145 | 146 | config(config: Partial) { 147 | type NodeConfigKey = keyof NodeConfig; 148 | 149 | for (const key of Object.keys(config) as NodeConfigKey[]) { 150 | const updateValue = config[key]; 151 | 152 | if (updateValue === undefined) { 153 | continue; 154 | } 155 | 156 | this.updateConfig(key, updateValue); 157 | } 158 | 159 | return this; 160 | } 161 | } 162 | 163 | // `Partial`` allows us to provide only a part of the 164 | // NodeConfig interface. 165 | new NodeAppBuilder().config({appName: 'ToDoApp'}); 166 | ``` 167 |
168 | 169 | - [`Required`](https://github.com/Microsoft/TypeScript/blob/2961bc3fc0ea1117d4e53bc8e97fa76119bc33e3/src/lib/es5.d.ts#L1408-L1413) - Make all properties in `T` required. 170 |
171 | 172 | Example 173 | 174 | 175 | [Playground](https://typescript-play.js.org/?target=6#code/AQ4SwOwFwUwJwGYEMDGNgGED21VQGJZwC2wA3gFCjXAzFJgA2A-AFzADOUckA5gNxUaIYjA4ckvGG07c+g6gF8KQkAgCuEFFDA5O6gEbEwUbLm2ESwABQIixACJIoSdgCUYAR3Vg4MACYAPGYuFvYAfACU5Ko0APRxwADKMBD+wFAAFuh2Vv7OSBlYGdmc8ABu8LHKsRyGxqY4oQT21pTCIHQMjOwA5DAAHgACxAAOjDAAdChYxL0ANLHUouKSMH0AEmAAhJhY6ozpAJ77GTCMjMCiV0ToSAb7UJPPC9WRgrEJwAAqR6MwSRQPFGUFocDgRHYxnEfGAowh-zgUCOwF6KwkUl6tXqJhCeEsxDaS1AXSYfUGI3GUxmc0WSneQA) 176 | 177 | ```ts 178 | interface ContactForm { 179 | email?: string; 180 | message?: string; 181 | } 182 | 183 | function submitContactForm(formData: Required) { 184 | // Send the form data to the server. 185 | } 186 | 187 | submitContactForm({ 188 | email: 'ex@mple.com', 189 | message: 'Hi! Could you tell me more about…', 190 | }); 191 | 192 | // TypeScript error: missing property 'message' 193 | submitContactForm({ 194 | email: 'ex@mple.com', 195 | }); 196 | ``` 197 |
198 | 199 | - [`Readonly`](https://github.com/Microsoft/TypeScript/blob/2961bc3fc0ea1117d4e53bc8e97fa76119bc33e3/src/lib/es5.d.ts#L1415-L1420) - Make all properties in `T` readonly. 200 |
201 | 202 | Example 203 | 204 | 205 | [Playground](https://typescript-play.js.org/?target=6#code/AQ4UwOwVwW2AZA9gc3mAbmANsA3gKFCOAHkAzMgGkOJABEwAjKZa2kAUQCcvEu32AMQCGAF2FYBIAL4BufDRABLCKLBcywgMZgEKZOoDCiCGSXI8i4hGEwwALmABnUVxXJ57YFgzZHSVF8sT1BpBSItLGEnJz1kAy5LLy0TM2RHACUwYQATEywATwAeAITjU3MAPnkrCJMXLigtUT4AClxgGztKbyDgaX99I1TzAEokr1BRAAslJwA6FIqLAF48TtswHp9MHDla9hJGACswZvmyLjAwAC8wVpm5xZHkUZDaMKIwqyWXYCW0oN4sNlsA1h0ug5gAByACyBQAggAHJHQ7ZBIFoXbzBjMCz7OoQP5YIaJNYQMAAdziCVaALGNSIAHomcAACoFJFgADKWjcSNEwG4vC4ji0wggEEQguiTnMEGALWAV1yAFp8gVgEjeFyuKICvMrCTgVxnst5jtsGC4ljsPNhXxGaAWcAAOq6YRXYDCRg+RWIcA5JSC+kWdCepQ+v3RYCU3RInzRMCGwlpC19NYBW1Ye08R1AA) 206 | 207 | ```ts 208 | enum LogLevel { 209 | Off, 210 | Debug, 211 | Error, 212 | Fatal 213 | }; 214 | 215 | interface LoggerConfig { 216 | name: string; 217 | level: LogLevel; 218 | } 219 | 220 | class Logger { 221 | config: Readonly; 222 | 223 | constructor({name, level}: LoggerConfig) { 224 | this.config = {name, level}; 225 | Object.freeze(this.config); 226 | } 227 | } 228 | 229 | const config: LoggerConfig = { 230 | name: 'MyApp', 231 | level: LogLevel.Debug 232 | }; 233 | 234 | const logger = new Logger(config); 235 | 236 | // TypeScript Error: cannot assign to read-only property. 237 | logger.config.level = LogLevel.Error; 238 | 239 | // We are able to edit config variable as we please. 240 | config.level = LogLevel.Error; 241 | ``` 242 |
243 | 244 | - [`Pick`](https://github.com/Microsoft/TypeScript/blob/2961bc3fc0ea1117d4e53bc8e97fa76119bc33e3/src/lib/es5.d.ts#L1422-L1427) - From `T`, pick a set of properties whose keys are in the union `K`. 245 |
246 | 247 | Example 248 | 249 | 250 | [Playground](https://typescript-play.js.org/?target=6#code/AQ4SwOwFwUwJwGYEMDGNgEE5TCgNugN4BQoZwOUBAXMAM5RyQDmA3KeSFABYCuAtgCMISMHloMmENh04oA9tBjQJjFuzIBfYrOAB6PcADCcGElh1gEGAHcKATwAO6ebyjB5CTNlwFwSxFR0BX5HeToYABNgBDh5fm8cfBg6AHIKG3ldA2BHOOcfFNpUygJ0pAhokr4hETFUgDpswywkggAFUwA3MFtgAF5gQgowKhhVKTYKGuFRcXo1aVZgbTIoJ3RW3xhOmB6+wfbcAGsAHi3kgBpgEtGy4AAfG54BWfqAPnZm4AAlZUj4MAkMA8GAGB4vEgfMlLLw6CwPBA8PYRmMgZVgAC6CgmI4cIommQELwICh8RBgKZKvALh1ur0bHQABR5PYMui0Wk7em2ADaAF0AJS0AASABUALIAGQAogR+Mp3CROCAFBBwVC2ikBpj5CgBIqGjizLA5TAFdAmalImAuqlBRoVQh5HBgEy1eDWfs7J5cjzGYKhroVfpDEhHM4MV6GRR5NN0JrtnRg6BVirTFBeHAKYmYY6QNpdB73LmCJZBlSAXAubtvczeSmQMNSuMbmKNgBlHFgPEUNwusBIPAAQlS1xetTmxT0SDoESgdD0C4aACtHMwxytLrohawgA) 251 | 252 | ```ts 253 | interface Article { 254 | title: string; 255 | thumbnail: string; 256 | content: string; 257 | } 258 | 259 | // Creates new type out of the `Article` interface composed 260 | // from the Articles' two properties: `title` and `thumbnail`. 261 | // `ArticlePreview = {title: string; thumbnail: string}` 262 | type ArticlePreview = Pick; 263 | 264 | // Render a list of articles using only title and description. 265 | function renderArticlePreviews(previews: ArticlePreview[]): HTMLElement { 266 | const articles = document.createElement('div'); 267 | 268 | for (const preview of previews) { 269 | // Append preview to the articles. 270 | } 271 | 272 | return articles; 273 | } 274 | 275 | const articles = renderArticlePreviews([ 276 | { 277 | title: 'TypeScript tutorial!', 278 | thumbnail: '/assets/ts.jpg' 279 | } 280 | ]); 281 | ``` 282 |
283 | 284 | - [`Record`](https://github.com/Microsoft/TypeScript/blob/2961bc3fc0ea1117d4e53bc8e97fa76119bc33e3/src/lib/es5.d.ts#L1429-L1434) - Construct a type with a set of properties `K` of type `T`. 285 |
286 | 287 | Example 288 | 289 | 290 | [Playground](https://typescript-play.js.org/?target=6#code/AQ4ejYAUHsGcCWAXBMB2dgwGbAKYC2ADgDYwCeeemCaWArgE7ADGMxAhmuQHQBQoYEnJE8wALKEARnkaxEKdMAC8wAOS0kstGuAAfdQBM8ANzxlRjXQbVaWACwC0JPB0NqA3HwGgIwAJJoWozYHCxixnAsjAhStADmwESMMJYo1Fi4HMCIaPEu+MRklHj8gpqyoeHAAKJFFFTAAN4+giDYCIxwSAByHAR4AFw5SDF5Xm2gJBzdfQPD3WPxE5PAlBxdAPLYNQAelgh4aOHDaPQEMowrIAC+3oJ+AMKMrlrAXFhSAFZ4LEhC9g4-0BmA4JBISXgiCkBQABpILrJ5MhUGhYcATGD6Bk4Hh-jNgABrPDkOBlXyQAAq9ngYmJpOAAHcEOCRjAXqwYODfoo6DhakUSph+Uh7GI4P0xER4Cj0OSQGwMP8tP1hgAlX7swwAHgRl2RvIANALSA08ABtAC6AD4VM1Wm0Kow0MMrYaHYJjGYLLJXZb3at1HYnC43Go-QHQDcvA6-JsmEJXARgCDgMYWAhjIYhDAU+YiMAAFIwex0ZmilMITCGF79TLAGRsAgJYAAZRwSEZGzEABFTOZUrJ5Yn+jwnWgeER6HB7AAKJrADpdXqS4ZqYultTG6azVfqHswPBbtauLY7fayQ7HIbAAAMwBuAEoYw9IBq2Ixs9h2eFMOQYPQObALQKJgggABeYhghCIpikkKRpOQRIknAsZUiIeCttECBEP8NSMCkjDDAARMGziuIYxHwYOjDCMBmDNnAuTxA6irdCOBB1Lh5Dqpqn66tISIykawBnOCtqqC0gbjqc9DgpGkxegOliyfJDrRkAA) 291 | 292 | ```ts 293 | // Positions of employees in our company. 294 | type MemberPosition = 'intern' | 'developer' | 'tech-lead'; 295 | 296 | // Interface describing properties of a single employee. 297 | interface Employee { 298 | firstName: string; 299 | lastName: string; 300 | yearsOfExperience: number; 301 | } 302 | 303 | // Create an object that has all possible `MemberPosition` values set as keys. 304 | // Those keys will store a collection of Employees of the same position. 305 | const team: Record = { 306 | intern: [], 307 | developer: [], 308 | 'tech-lead': [], 309 | }; 310 | 311 | // Our team has decided to help John with his dream of becoming Software Developer. 312 | team.intern.push({ 313 | firstName: 'John', 314 | lastName: 'Doe', 315 | yearsOfExperience: 0 316 | }); 317 | 318 | // `Record` forces you to initialize all of the property keys. 319 | // TypeScript Error: "tech-lead" property is missing 320 | const teamEmpty: Record = { 321 | intern: null, 322 | developer: null, 323 | }; 324 | ``` 325 |
326 | 327 | - [`Exclude`](https://github.com/Microsoft/TypeScript/blob/2961bc3fc0ea1117d4e53bc8e97fa76119bc33e3/src/lib/es5.d.ts#L1436-L1439) - Exclude from `T` those types that are assignable to `U`. 328 |
329 | 330 | Example 331 | 332 | 333 | [Playground](https://typescript-play.js.org/?target=6#code/JYOwLgpgTgZghgYwgAgMrQG7QMIHsQzADmyA3gFDLIAOuUYAXMiAK4A2byAPsgM5hRQJHqwC2AI2gBucgF9y5MAE9qKAEoQAjiwj8AEnBAATNtGQBeZAAooWphu26wAGmS3e93bRC8IASgsAPmRDJRlyAHoI5ABRAA8ENhYjFFYOZGVVZBgoXFFkAAM0zh5+QRBhZhYJaAKAOkjogEkQZAQ4X2QAdwALCFbaemRgXmQtFjhOMFwq9K6ULuB0lk6U+HYwZAxJnQaYFhAEMGB8ZCIIMAAFOjAANR2IK0HGWISklIAedCgsKDwCYgAbQA5M9gQBdVzFQJ+JhiSRQMiUYYwayZCC4VHPCzmSzAspCYEBWxgFhQAZwKC+FpgJ43VwARgADH4ZFQSWSBjcZPJyPtDsdTvxKWBvr8rD1DCZoJ5HPopaYoK4EPhCEQmGKcKriLCtrhgEYkVQVT5Nr4fmZLLZtMBbFZgT0wGBqES6ghbHBIJqoBKFdBWQpjfh+DQbhY2tqiHVsbjLMVkAB+ZAAZiZaeQTHOVxu9ySjxNaujNwDVHNvzqbBGkBAdPoAfkQA) 334 | 335 | ```ts 336 | interface ServerConfig { 337 | port: null | string | number; 338 | } 339 | 340 | type RequestHandler = (request: Request, response: Response) => void; 341 | 342 | // Exclude `null` type from `null | string | number`. 343 | // In case the port is equal to `null`, we will use default value. 344 | function getPortValue(port: Exclude): number { 345 | if (typeof port === 'string') { 346 | return parseInt(port, 10); 347 | } 348 | 349 | return port; 350 | } 351 | 352 | function startServer(handler: RequestHandler, config: ServerConfig): void { 353 | const server = require('http').createServer(handler); 354 | 355 | const port = config.port === null ? 3000 : getPortValue(config.port); 356 | server.listen(port); 357 | } 358 | ``` 359 |
360 | 361 | - [`Extract`](https://github.com/Microsoft/TypeScript/blob/2961bc3fc0ea1117d4e53bc8e97fa76119bc33e3/src/lib/es5.d.ts#L1441-L1444) - Extract from `T` those types that are assignable to `U`. 362 |
363 | 364 | Example 365 | 366 | 367 | [Playground](https://typescript-play.js.org/?target=6#code/CYUwxgNghgTiAEAzArgOzAFwJYHtXzSwEdkQBJYACgEoAueVZAWwCMQYBuAKDDwGcM8MgBF4AXngBlAJ6scESgHIRi6ty5ZUGdoihgEABXZ888AN5d48ANoiAuvUat23K6ihMQ9ATE0BzV3goPy8GZjZOLgBfLi4Aejj4AEEICBwAdz54MAALKFQQ+BxEeAAHY1NgKAwoIKy0grr4DByEUpgccpgMaXgAaxBerCzi+B9-ZulygDouFHRsU1z8kKMYE1RhaqgAHkt4AHkWACt4EAAPbVRgLLWNgBp9gGlBs8uQa6yAUUuYPQwdgNpKM7nh7mMML4CgA+R5WABqUAgpDeVxuhxO1he0jsXGh8EoOBO9COx3BQPo2PBADckaR6IjkSA6PBqTgsMBzPsicdrEC7OJWXSQNwYvFEgAVTS9JLXODpeDpKBZFg4GCoWa8VACIJykAKiQWKy2YQOAioYikCg0OEMDyhRSy4DyxS24KhAAMjyi6gS8AAwjh5OD0iBFHAkJoEOksC1mnkMJq8gUQKDNttKPlnfrwYp3J5XfBHXqoKpfYkAOI4ansTxaeDADmoRSCCBYAbxhC6TDx6rwYHIRX5bScjA4bLJwoDmDwDkfbA9JMrVMVdM1TN69LgkTgwgkchUahqIA) 368 | 369 | ```ts 370 | declare function uniqueId(): number; 371 | 372 | const ID = Symbol('ID'); 373 | 374 | interface Person { 375 | [ID]: number; 376 | name: string; 377 | age: number; 378 | } 379 | 380 | // Allows changing the person data as long as the property key is of string type. 381 | function changePersonData< 382 | Obj extends Person, 383 | Key extends Extract, 384 | Value extends Obj[Key] 385 | > (obj: Obj, key: Key, value: Value): void { 386 | obj[key] = value; 387 | } 388 | 389 | // Tiny Andrew was born. 390 | const andrew = { 391 | [ID]: uniqueId(), 392 | name: 'Andrew', 393 | age: 0, 394 | }; 395 | 396 | // Cool, we're fine with that. 397 | changePersonData(andrew, 'name', 'Pony'); 398 | 399 | // Goverment didn't like the fact that you wanted to change your identity. 400 | changePersonData(andrew, ID, uniqueId()); 401 | ``` 402 |
403 | 404 | - [`NonNullable`](https://github.com/Microsoft/TypeScript/blob/2961bc3fc0ea1117d4e53bc8e97fa76119bc33e3/src/lib/es5.d.ts#L1446-L1449) - Exclude `null` and `undefined` from `T`. 405 |
406 | 407 | Example 408 | 409 | Works with strictNullChecks set to true. (Read more here) 410 | 411 | [Playground](https://typescript-play.js.org/?target=6#code/C4TwDgpgBACg9gJ2AOQK4FsBGEFQLxQDOwCAlgHYDmUAPlORtrnQwDasDcAUFwPQBU-WAEMkUOADMowqAGNWwwoSgATCBIqlgpOOSjAAFsOBRSy1IQgr9cKJlSlW1mZYQA3HFH68u8xcoBlHA8EACEHJ08Aby4oKDBUTFZSWXjEFEYcAEIALihkXTR2YSSIAB54JDQsHAA+blj4xOTUsHSACkMzPKD3HHDHNQQAGjSkPMqMmoQASh7g-oihqBi4uNIpdraxPAI2VhmVxrX9AzMAOm2ppnwoAA4ABifuE4BfKAhWSyOTuK7CS7pao3AhXF5rV48E4ICDAVAIPT-cGQyG+XTEIgLMJLTx7CAAdygvRCA0iCHaMwarhJOIQjUBSHaACJHk8mYdeLwxtdcVAAOSsh58+lXdr7Dlcq7A3n3J4PEUdADMcspUE53OluAIUGVTx46oAKuAIAFZGQwCYAKIIBCILjUxaDHAMnla+iodjcIA) 412 | 413 | ```ts 414 | type PortNumber = string | number | null; 415 | 416 | /** Part of a class definition that is used to build a server */ 417 | class ServerBuilder { 418 | portNumber!: NonNullable; 419 | 420 | port(this: ServerBuilder, port: PortNumber): ServerBuilder { 421 | if (port == null) { 422 | this.portNumber = 8000; 423 | } else { 424 | this.portNumber = port; 425 | } 426 | 427 | return this; 428 | } 429 | } 430 | 431 | const serverBuilder = new ServerBuilder(); 432 | 433 | serverBuilder 434 | .port('8000') // portNumber = '8000' 435 | .port(null) // portNumber = 8000 436 | .port(3000); // portNumber = 3000 437 | 438 | // TypeScript error 439 | serverBuilder.portNumber = null; 440 | ``` 441 |
442 | 443 | - [`Parameters`](https://github.com/Microsoft/TypeScript/blob/2961bc3fc0ea1117d4e53bc8e97fa76119bc33e3/src/lib/es5.d.ts#L1451-L1454) - Obtain the parameters of a function type in a tuple. 444 |
445 | 446 | Example 447 | 448 | 449 | [Playground](https://typescript-play.js.org/?target=6#code/GYVwdgxgLglg9mABAZwBYmMANgUwBQxgAOIUAXIgIZgCeA2gLoCUFAbnDACaIDeAUIkQB6IYgCypSlBxUATrMo1ECsJzgBbLEoipqAc0J7EMKMgDkiHLnU4wp46pwAPHMgB0fAL58+oSLARECEosLAA5ABUYG2QAHgAxJGdpVWREPDdMylk9ZApqemZEAF4APipacrw-CApEgBogkKwAYThwckQwEHUAIxxZJl4BYVEImiIZKF0oZRwiWVdbeygJmThgOYgcGFYcbhqApCJsyhtpWXcR1cnEePBoeDAABVPzgbTixFeFd8uEsClADcIxGiygIFkSEOT3SmTc2VydQeRx+ZxwF2QQ34gkEwDgsnSuFmMBKiAADEDjIhYk1Qm0OlSYABqZnYka4xA1DJZHJYkGc7yCbyeRA+CAIZCzNAYbA4CIAdxg2zJwVCkWirjwMswuEaACYmCCgA) 450 | 451 | ```ts 452 | function shuffle(input: any[]): void { 453 | // Mutate array randomly changing its' elements indexes. 454 | } 455 | 456 | function callNTimes any> (func: Fn, callCount: number) { 457 | // Type that represents the type of the received function parameters. 458 | type FunctionParameters = Parameters; 459 | 460 | return function (...args: FunctionParameters) { 461 | for (let i = 0; i < callCount; i++) { 462 | func(...args); 463 | } 464 | } 465 | } 466 | 467 | const shuffleTwice = callNTimes(shuffle, 2); 468 | ``` 469 |
470 | 471 | - [`ConstructorParameters`](https://github.com/Microsoft/TypeScript/blob/2961bc3fc0ea1117d4e53bc8e97fa76119bc33e3/src/lib/es5.d.ts#L1456-L1459) - Obtain the parameters of a constructor function type in a tuple. 472 |
473 | 474 | Example 475 | 476 | 477 | [Playground](https://typescript-play.js.org/?target=6#code/MYGwhgzhAECCBOAXAlqApgWQPYBM0mgG8AoaaFRENALmgkXmQDsBzAblOmCycTV4D8teo1YdO3JiICuwRFngAKClWENmLAJRFOZRAAtkEAHQq00ALzlklNBzIBfYk+KhIMAJJTEYJsDQAwmDA+mgAPAAq0GgAHnxMODCKTGgA7tCKxllg8CwQtL4AngDaALraFgB80EWa1SRkAA6MAG5gfNAB4FABPDJyCrQR9tDNyG0dwMGhtBhgjWEiGgA00F70vv4RhY3hEZXVVinpc42KmuJkkv3y8Bly8EPaDWTkhiZd7r3e8LK3llwGCMXGQWGhEOsfH5zJlsrl8p0+gw-goAAo5MAAW3BaHgEEilU0tEhmzQ212BJ0ry4SOg+kg+gBBiMximIGA0nAfAQLGk2N4EAAEgzYcYcnkLsRdDTvNEYkYUKwSdCme9WdM0MYwYhFPSIPpJdTkAAzDKxBUaZX+aAAQgsVmkCTQxuYaBw2ng4Ok8CYcotSu8pMur09iG9vuObxZnx6SN+AyUWTF8MN0CcZE4Ywm5jZHK5aB5fP4iCFIqT4oRRTKRLo6lYVNeAHpG50wOzOe1zHr9NLQ+HoABybsD4HOKXXRA1JCoKhBELmI5pNaB6Fz0KKBAodDYPAgSUTmqYsAALx4m5nC6nW9nGq14KtaEUA9gR9PvuNCjQ9BgACNvcwNBtAcLiAA) 478 | 479 | ```ts 480 | class ArticleModel { 481 | title: string; 482 | content?: string; 483 | 484 | constructor(title: string) { 485 | this.title = title; 486 | } 487 | } 488 | 489 | class InstanceCache any)> { 490 | private ClassConstructor: T; 491 | private cache: Map> = new Map(); 492 | 493 | constructor (ctr: T) { 494 | this.ClassConstructor = ctr; 495 | } 496 | 497 | getInstance (...args: ConstructorParameters): InstanceType { 498 | const hash = this.calculateArgumentsHash(...args); 499 | 500 | const existingInstance = this.cache.get(hash); 501 | if (existingInstance !== undefined) { 502 | return existingInstance; 503 | } 504 | 505 | return new this.ClassConstructor(...args); 506 | } 507 | 508 | private calculateArgumentsHash(...args: any[]): string { 509 | // Calculate hash. 510 | return 'hash'; 511 | } 512 | } 513 | 514 | const articleCache = new InstanceCache(ArticleModel); 515 | const amazonArticle = articleCache.getInstance('Amazon forests burining!'); 516 | ``` 517 |
518 | 519 | - [`ReturnType`](https://github.com/Microsoft/TypeScript/blob/2961bc3fc0ea1117d4e53bc8e97fa76119bc33e3/src/lib/es5.d.ts#L1461-L1464) – Obtain the return type of a function type. 520 |
521 | 522 | Example 523 | 524 | 525 | [Playground](https://typescript-play.js.org/?target=6#code/MYGwhgzhAECSAmICmBlJAnAbgS2E6A3gFDTTwD2AcuQC4AW2AdgOYAUAlAFzSbnbyEAvkWFFQkGJSQB3GMVI1sNZNwg10TZgG4S0YOUY0kh1es07d+xmvQBXYDXLpWi5UlMaWAGj0GjJ6BtNdkJdBQYIADpXZGgAXmgYpB1ScOwoq38aeN9DYxoU6GFRKzVoJjUwRjwAYXJbPPRuAFkwAAcAHgAxBodsAx9GWwBbACMMAD4cxhloVraOCyYjdAAzMDxoOut1e0d0UNIZ6WhWSPOwdGYIbiqATwBtAF0uaHudUQB6ACpv6ABpJBINqJdAbADW0Do5BOw3u5R2VTwMHIq2gAANtjZ0bkbHsnFCwJh8ONjHp0EgwEZ4JFoN9PkRVr1FAZoMwkDRYIjqkgOrosepoEgAB7+eAwAV2BxOLy6ACCVxgIrFEoMeOl6AACpcwMMORgIB1JRMiBNWKVdhruJKfOdIpdrtwFddXlzKjyACp3Nq842HaDIbL6BrZBIVGhIpB1EMYSLsmjmtWW-YhAA+qegAAYLKQLQj3ZsEsdccmnGcLor2Dn8xGedHGpEIBzEzspfsfMHDNAANTQACMVaIljV5GQkRA5DYmIpVKQAgAJARO9le33BDXIyi0YuLW2nJFGLqkOvxFB0YPdBSaLZ0IwNzyPkO8-xkGgsLh8Al427a3hWAhXwwHA8EHT5PmgAB1bAQBAANJ24adKWpft72RaBUTgRBUCAj89HAM8xCTaBjggABRQx0DuHJv25P9dCkWRZVIAAiBjoFImpmjlFBgA0NpsjadByDacgIDAEAIAAQmYpjoGYgAZSBsmGPw6DtZiiFA8CoJguDmAQmoZ2QvtUKQLdoAYmBTwgdEiCAA) 526 | 527 | ```ts 528 | /** Provides every element of the iterable `iter` into the `callback` function and stores the results in an array. */ 529 | function mapIter< 530 | Elem, 531 | Func extends (elem: Elem) => any, 532 | Ret extends ReturnType 533 | >(iter: Iterable, callback: Func): Ret[] { 534 | const mapped: Ret[] = []; 535 | 536 | for (const elem of iter) { 537 | mapped.push(callback(elem)); 538 | } 539 | 540 | return mapped; 541 | } 542 | 543 | const setObject: Set = new Set(); 544 | const mapObject: Map = new Map(); 545 | 546 | mapIter(setObject, (value: string) => value.indexOf('Foo')); // number[] 547 | 548 | mapIter(mapObject, ([key, value]: [number, string]) => { 549 | return key % 2 === 0 ? value : 'Odd'; 550 | }); // string[] 551 | ``` 552 |
553 | 554 | - [`InstanceType`](https://github.com/Microsoft/TypeScript/blob/2961bc3fc0ea1117d4e53bc8e97fa76119bc33e3/src/lib/es5.d.ts#L1466-L1469) – Obtain the instance type of a constructor function type. 555 |
556 | 557 | Example 558 | 559 | 560 | [Playground](https://typescript-play.js.org/?target=6#code/MYGwhgzhAECSAmICmBlJAnAbgS2E6A3gFDTTwD2AcuQC4AW2AdgOYAUAlAFzSbnbyEAvkWFFQkGJSQB3GMVI1sNZNwg10TZgG4S0YOUY0kh1es07d+xmvQBXYDXLpWi5UlMaWAGj0GjJ6BtNdkJdBQYIADpXZGgAXmgYpB1ScOwoq38aeN9DYxoU6GFRKzVoJjUwRjwAYXJbPPRuAFkwAAcAHgAxBodsAx9GWwBbACMMAD4cxhloVraOCyYjdAAzMDxoOut1e0d0UNIZ6WhWSPOwdGYIbiqATwBtAF0uaHudUQB6ACpv6ABpJBINqJdAbADW0Do5BOw3u5R2VTwMHIq2gAANtjZ0bkbHsnFCwJh8ONjHp0EgwEZ4JFoN9PkRVr1FAZoMwkDRYIjqkgOrosepoEgAB7+eAwAV2BxOLy6ACCVxgIrFEoMeOl6AACpcwMMORgIB1JRMiBNWKVdhruJKfOdIpdrtwFddXlzKjyACp3Nq842HaDIbL6BrZBIVGhIpB1EMYSLsmjmtWW-YhAA+qegAAYLKQLQj3ZsEsdccmnGcLor2Dn8xGedHGpEIBzEzspfsfMHDNAANTQACMVaIljV5GQkRA5DYmIpVKQAgAJARO9le33BDXIyi0YuLW2nJFGLqkOvxFB0YPdBSaLZ0IwNzyPkO8-xkGgsLh8Al427a3hWAhXwwHA8EHT5PmgAB1bAQBAANJ24adKWpft72RaBUTgRBUCAj89HAM8xCTaBjggABRQx0DuHJv25P9dCkWRZVIAAiBjoFImpmjlFBgA0NpsjadByDacgIDAEAIAAQmYpjoGYgAZSBsmGPw6DtZiiFA8CoJguDmAQmoZ2QvtUKQLdoAYmBTwgdEiCAA) 561 | 562 | ```ts 563 | class IdleService { 564 | doNothing (): void {} 565 | } 566 | 567 | class News { 568 | title: string; 569 | content: string; 570 | 571 | constructor(title: string, content: string) { 572 | this.title = title; 573 | this.content = content; 574 | } 575 | } 576 | 577 | const instanceCounter: Map = new Map(); 578 | 579 | interface Constructor { 580 | new(...args: any[]): any; 581 | } 582 | 583 | // Keep track how many instances of `Constr` constructor have been created. 584 | function getInstance< 585 | Constr extends Constructor, 586 | Args extends ConstructorParameters 587 | >(constructor: Constr, ...args: Args): InstanceType { 588 | let count = instanceCounter.get(constructor) || 0; 589 | 590 | const instance = new constructor(...args); 591 | 592 | instanceCounter.set(constructor, count + 1); 593 | 594 | console.log(`Created ${count + 1} instances of ${Constr.name} class`); 595 | 596 | return instance; 597 | } 598 | 599 | 600 | const idleService = getInstance(IdleService); 601 | // Will log: `Created 1 instances of IdleService class` 602 | const newsEntry = getInstance(News, 'New ECMAScript proposals!', 'Last month...'); 603 | // Will log: `Created 1 instances of News class` 604 | ``` 605 |
606 | 607 | - [`Omit`](https://github.com/microsoft/TypeScript/blob/71af02f7459dc812e85ac31365bfe23daf14b4e4/src/lib/es5.d.ts#L1446) – Constructs a type by picking all properties from T and then removing K. 608 |
609 | 610 | Example 611 | 612 | 613 | [Playground](https://typescript-play.js.org/?target=6#code/JYOwLgpgTgZghgYwgAgIImAWzgG2QbwChlks4BzCAVShwC5kBnMKUcgbmKYAcIFgIjBs1YgOXMpSFMWbANoBdTiW5woFddwAW0kfKWEAvoUIB6U8gDCUCHEiNkICAHdkYAJ69kz4GC3JcPG4oAHteKDABBxCYNAxsPFBIWEQUCAAPJG4wZABySUFcgJAAEzMLXNV1ck0dIuCw6EjBADpy5AB1FAQ4EGQAV0YUP2AHDy8wEOQbUugmBLwtEIA3OcmQnEjuZBgQqE7gAGtgZAhwKHdkHFGwNvGUdDIcAGUliIBJEF3kAF5kAHlML4ADyPBIAGjyBUYRQAPnkqho4NoYQA+TiEGD9EAISIhPozErQMG4AASK2gn2+AApek9pCSXm8wFSQooAJQMUkAFQAsgAZACiOAgmDOOSIJAQ+OYyGl4DgoDmf2QJRCCH6YvALQQNjsEGFovF1NyJWAy1y7OUyHMyE+yRAuFImG4Iq1YDswHxbRINjA-SgfXlHqVUE4xiAA) 614 | 615 | ```ts 616 | interface Animal { 617 | imageUrl: string; 618 | species: string; 619 | images: string[]; 620 | paragraphs: string[]; 621 | } 622 | 623 | // Creates new type with all properties of the `Animal` interface 624 | // except 'images' and 'paragraphs' properties. We can use this 625 | // type to render small hover tooltip for a wiki entry list. 626 | type AnimalShortInfo = Omit; 627 | 628 | function renderAnimalHoverInfo (animals: AnimalShortInfo[]): HTMLElement { 629 | const container = document.createElement('div'); 630 | // Internal implementation. 631 | return container; 632 | } 633 | ``` 634 |
635 | 636 | You can find some examples in the [TypeScript docs](https://www.typescriptlang.org/docs/handbook/advanced-types.html#predefined-conditional-types). 637 | 638 | ## Maintainers 639 | 640 | - [Sindre Sorhus](https://github.com/sindresorhus) 641 | - [Jarek Radosz](https://github.com/CvX) 642 | - [Dimitri Benin](https://github.com/BendingBender) 643 | 644 | ## License 645 | 646 | (MIT OR CC0-1.0) 647 | 648 | --- 649 | 650 |
651 | 652 | Get professional support for this package with a Tidelift subscription 653 | 654 |
655 | 656 | Tidelift helps make open source sustainable for maintainers while giving companies
assurances about security, maintenance, and licensing for their dependencies. 657 |
658 |
659 | -------------------------------------------------------------------------------- /media/logo.svg: -------------------------------------------------------------------------------- 1 | 2 | --------------------------------------------------------------------------------