The response has been limited to 50k tokens of the smallest files in the repo. You can remove this limitation by removing the max tokens filter.
├── .editorconfig
├── .gitattributes
├── .github
    ├── ISSUE_TEMPLATE
    │   ├── 1 new type.yml
    │   ├── 2 bug report.yml
    │   └── 3 enhancement.md
    ├── contributing.md
    ├── dependabot.yml
    ├── funding.yml
    ├── pull_request_template.md
    ├── security.md
    └── workflows
    │   ├── main.yml
    │   └── ts-canary.yml
├── .gitignore
├── .npmrc
├── index.d.ts
├── license-cc0
├── license-mit
├── lint-rules
    ├── import-path.js
    └── source-files-extension.js
├── media
    ├── logo.png
    ├── logo.sketch
    ├── logo.svg
    ├── logo@2x.png
    └── readme.md
├── package.json
├── readme.md
├── source
    ├── all-extend.d.ts
    ├── all-union-fields.d.ts
    ├── and.d.ts
    ├── array-indices.d.ts
    ├── array-slice.d.ts
    ├── array-splice.d.ts
    ├── array-tail.d.ts
    ├── array-values.d.ts
    ├── arrayable.d.ts
    ├── async-return-type.d.ts
    ├── asyncify.d.ts
    ├── basic.d.ts
    ├── camel-case.d.ts
    ├── camel-cased-properties-deep.d.ts
    ├── camel-cased-properties.d.ts
    ├── characters.d.ts
    ├── conditional-except.d.ts
    ├── conditional-keys.d.ts
    ├── conditional-pick-deep.d.ts
    ├── conditional-pick.d.ts
    ├── conditional-simplify-deep.d.ts
    ├── conditional-simplify.d.ts
    ├── delimiter-case.d.ts
    ├── delimiter-cased-properties-deep.d.ts
    ├── delimiter-cased-properties.d.ts
    ├── distributed-omit.d.ts
    ├── distributed-pick.d.ts
    ├── empty-object.d.ts
    ├── enforce-optional.d.ts
    ├── entries.d.ts
    ├── entry.d.ts
    ├── exact.d.ts
    ├── except.d.ts
    ├── exclude-strict.d.ts
    ├── extends-strict.d.ts
    ├── extract-strict.d.ts
    ├── find-global-type.d.ts
    ├── fixed-length-array.d.ts
    ├── get.d.ts
    ├── global-this.d.ts
    ├── globals
    │   ├── index.d.ts
    │   └── observable-like.d.ts
    ├── greater-than-or-equal.d.ts
    ├── greater-than.d.ts
    ├── has-optional-keys.d.ts
    ├── has-readonly-keys.d.ts
    ├── has-required-keys.d.ts
    ├── has-writable-keys.d.ts
    ├── if-any.d.ts
    ├── if-empty-object.d.ts
    ├── if-never.d.ts
    ├── if-null.d.ts
    ├── if-unknown.d.ts
    ├── if.d.ts
    ├── includes.d.ts
    ├── int-closed-range.d.ts
    ├── int-range.d.ts
    ├── internal
    │   ├── array.d.ts
    │   ├── characters.d.ts
    │   ├── index.d.ts
    │   ├── keys.d.ts
    │   ├── numeric.d.ts
    │   ├── object.d.ts
    │   ├── string.d.ts
    │   ├── tuple.d.ts
    │   └── type.d.ts
    ├── invariant-of.d.ts
    ├── is-any.d.ts
    ├── is-equal.d.ts
    ├── is-float.d.ts
    ├── is-integer.d.ts
    ├── is-literal.d.ts
    ├── is-lowercase.d.ts
    ├── is-never.d.ts
    ├── is-null.d.ts
    ├── is-nullable.d.ts
    ├── is-optional.d.ts
    ├── is-tuple.d.ts
    ├── is-union.d.ts
    ├── is-unknown.d.ts
    ├── is-uppercase.d.ts
    ├── iterable-element.d.ts
    ├── join.d.ts
    ├── json-value.d.ts
    ├── jsonifiable.d.ts
    ├── jsonify.d.ts
    ├── kebab-case.d.ts
    ├── kebab-cased-properties-deep.d.ts
    ├── kebab-cased-properties.d.ts
    ├── key-as-string.d.ts
    ├── keys-of-union.d.ts
    ├── last-array-element.d.ts
    ├── less-than-or-equal.d.ts
    ├── less-than.d.ts
    ├── literal-to-primitive-deep.d.ts
    ├── literal-to-primitive.d.ts
    ├── literal-union.d.ts
    ├── merge-deep.d.ts
    ├── merge-exclusive.d.ts
    ├── merge.d.ts
    ├── multidimensional-array.d.ts
    ├── multidimensional-readonly-array.d.ts
    ├── non-empty-object.d.ts
    ├── non-empty-string.d.ts
    ├── non-empty-tuple.d.ts
    ├── numeric.d.ts
    ├── omit-deep.d.ts
    ├── omit-index-signature.d.ts
    ├── opaque.d.ts
    ├── optional-keys-of.d.ts
    ├── or.d.ts
    ├── override-properties.d.ts
    ├── package-json.d.ts
    ├── partial-deep.d.ts
    ├── partial-on-undefined-deep.d.ts
    ├── pascal-case.d.ts
    ├── pascal-cased-properties-deep.d.ts
    ├── pascal-cased-properties.d.ts
    ├── paths.d.ts
    ├── pick-deep.d.ts
    ├── pick-index-signature.d.ts
    ├── primitive.d.ts
    ├── promisable.d.ts
    ├── readonly-deep.d.ts
    ├── readonly-keys-of.d.ts
    ├── readonly-tuple.d.ts
    ├── remove-prefix.d.ts
    ├── replace.d.ts
    ├── require-all-or-none.d.ts
    ├── require-at-least-one.d.ts
    ├── require-exactly-one.d.ts
    ├── require-one-or-none.d.ts
    ├── required-deep.d.ts
    ├── required-keys-of.d.ts
    ├── schema.d.ts
    ├── screaming-snake-case.d.ts
    ├── set-field-type.d.ts
    ├── set-non-nullable-deep.d.ts
    ├── set-non-nullable.d.ts
    ├── set-optional.d.ts
    ├── set-parameter-type.d.ts
    ├── set-readonly.d.ts
    ├── set-required-deep.d.ts
    ├── set-required.d.ts
    ├── set-return-type.d.ts
    ├── shared-union-fields-deep.d.ts
    ├── shared-union-fields.d.ts
    ├── simplify-deep.d.ts
    ├── simplify.d.ts
    ├── single-key-object.d.ts
    ├── snake-case.d.ts
    ├── snake-cased-properties-deep.d.ts
    ├── snake-cased-properties.d.ts
    ├── split.d.ts
    ├── spread.d.ts
    ├── string-repeat.d.ts
    ├── string-slice.d.ts
    ├── stringified.d.ts
    ├── structured-cloneable.d.ts
    ├── subtract.d.ts
    ├── sum.d.ts
    ├── tagged-union.d.ts
    ├── tagged.d.ts
    ├── trim.d.ts
    ├── tsconfig-json.d.ts
    ├── tuple-to-object.d.ts
    ├── tuple-to-union.d.ts
    ├── typed-array.d.ts
    ├── undefined-on-partial-deep.d.ts
    ├── union-to-intersection.d.ts
    ├── union-to-tuple.d.ts
    ├── unknown-array.d.ts
    ├── unknown-map.d.ts
    ├── unknown-record.d.ts
    ├── unknown-set.d.ts
    ├── value-of.d.ts
    ├── words.d.ts
    ├── writable-deep.d.ts
    ├── writable-keys-of.d.ts
    └── writable.d.ts
├── test-d
    ├── abstract-class.ts
    ├── all-extend.ts
    ├── all-union-fields.ts
    ├── and.ts
    ├── array-indices.ts
    ├── array-slice.ts
    ├── array-splice.ts
    ├── array-tail.ts
    ├── array-values.ts
    ├── arrayable.ts
    ├── async-return-type.ts
    ├── asyncify.ts
    ├── camel-case.ts
    ├── camel-cased-properties-deep.ts
    ├── camel-cased-properties.ts
    ├── class.ts
    ├── conditional-except.ts
    ├── conditional-keys.ts
    ├── conditional-pick-deep.ts
    ├── conditional-pick.ts
    ├── conditional-simplify-deep.ts
    ├── conditional-simplify.ts
    ├── delimiter-case.ts
    ├── delimiter-cased-properties-deep.ts
    ├── delimiter-cased-properties.ts
    ├── distributed-omit.ts
    ├── distributed-pick.ts
    ├── empty-object.ts
    ├── enforce-optional.ts
    ├── entries.ts
    ├── exact.ts
    ├── except.ts
    ├── exclude-strict.ts
    ├── extends-strict.ts
    ├── extract-strict.ts
    ├── find-global-type.ts
    ├── fixed-length-array.ts
    ├── get.ts
    ├── global-this.ts
    ├── greater-than-or-equal.ts
    ├── greater-than.ts
    ├── has-optional-keys.ts
    ├── has-readonly-keys.ts
    ├── has-required-keys.ts
    ├── has-writable-keys.ts
    ├── if-any.ts
    ├── if-never.ts
    ├── if-unknown.ts
    ├── if.ts
    ├── includes.ts
    ├── int-closed-range.ts
    ├── int-range.ts
    ├── internal
    │   ├── apply-default-options.ts
    │   ├── build-tuple.ts
    │   ├── collapse-literals-in-union.ts
    │   ├── collapse-rest-element.ts
    │   ├── has-multiple-call-signatures.ts
    │   ├── homomorphic-pick.ts
    │   ├── if-not-any-or-never.ts
    │   ├── is-array-readonly.ts
    │   ├── is-not-false.ts
    │   ├── is-number-like.ts
    │   ├── is-numeric.ts
    │   ├── is-whitespace.ts
    │   ├── not.ts
    │   ├── number-absolute.ts
    │   ├── object-value.ts
    │   ├── readonly-keys-of-union.ts
    │   ├── require-none.ts
    │   ├── tuple-max.ts
    │   ├── tuple-min.ts
    │   └── value-of-union.ts
    ├── invariant-of.ts
    ├── is-any.ts
    ├── is-equal.ts
    ├── is-float.ts
    ├── is-integer.ts
    ├── is-literal.ts
    ├── is-lowercase.ts
    ├── is-never.ts
    ├── is-null.ts
    ├── is-nullable.ts
    ├── is-optional.ts
    ├── is-tuple.ts
    ├── is-union.ts
    ├── is-unknown.ts
    ├── is-uppercase.ts
    ├── iterable-element.ts
    ├── join.ts
    ├── jsonifiable.ts
    ├── jsonify.ts
    ├── kebab-case.ts
    ├── kebab-cased-properties-deep.ts
    ├── kebab-cased-properties.ts
    ├── key-as-string.ts
    ├── keys-of-union.ts
    ├── last-array-element.ts
    ├── less-than-or-equal.ts
    ├── less-than.ts
    ├── literal-to-primitive-deep.ts
    ├── literal-to-primitive.ts
    ├── merge-deep.ts
    ├── merge-exclusive.ts
    ├── merge.ts
    ├── multidimensional-array.ts
    ├── multidimensional-readonly-array.ts
    ├── non-empty-object.ts
    ├── non-empty-string.ts
    ├── non-empty-tuple.ts
    ├── numeric.ts
    ├── observable-like.ts
    ├── omit-deep.ts
    ├── omit-index-signature.ts
    ├── opaque.ts
    ├── optional-keys-of.ts
    ├── or.ts
    ├── override-properties.ts
    ├── package-json.ts
    ├── partial-deep.ts
    ├── partial-on-undefined-deep.ts
    ├── pascal-case.ts
    ├── pascal-cased-properties-deep.ts
    ├── pascal-cased-properties.ts
    ├── paths.ts
    ├── pick-deep.ts
    ├── pick-index-signature.ts
    ├── promisable.ts
    ├── readonly-deep.ts
    ├── readonly-keys-of.ts
    ├── readonly-tuple.ts
    ├── remove-prefix.ts
    ├── replace.ts
    ├── require-all-or-none.ts
    ├── require-at-least-one.ts
    ├── require-exactly-one.ts
    ├── require-one-or-none.ts
    ├── required-deep.ts
    ├── required-keys-of.ts
    ├── schema.ts
    ├── screaming-snake-case.ts
    ├── set-field-type.ts
    ├── set-non-nullable-deep.ts
    ├── set-non-nullable.ts
    ├── set-optional.ts
    ├── set-parameter-type.ts
    ├── set-readonly.ts
    ├── set-required-deep.ts
    ├── set-required.ts
    ├── set-return-type.ts
    ├── shared-union-fields-deep.ts
    ├── shared-union-fields.ts
    ├── simplify-deep.ts
    ├── simplify.ts
    ├── single-key-object.ts
    ├── snake-case.ts
    ├── snake-cased-properties-deep.ts
    ├── snake-cased-properties.ts
    ├── split.ts
    ├── spread.ts
    ├── string-repeat.ts
    ├── string-slice.ts
    ├── stringified.ts
    ├── structured-cloneable.ts
    ├── subtract.ts
    ├── sum.ts
    ├── tagged-union.ts
    ├── trim.ts
    ├── ts41.ts
    ├── tsconfig-json.ts
    ├── tuple-to-object.ts
    ├── tuple-to-union.ts
    ├── undefined-on-partial-deep.ts
    ├── union-to-intersection.ts
    ├── union-to-tuple.ts
    ├── unknown-array.ts
    ├── unknown-map.ts
    ├── unknown-record.ts
    ├── unknown-set.ts
    ├── value-of.ts
    ├── words.ts
    ├── writable-deep.ts
    ├── writable-keys-of.ts
    └── writable.ts
├── tsconfig.json
└── xo.config.js


/.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 | 


--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto eol=lf
2 | 


--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/1 new type.yml:
--------------------------------------------------------------------------------
 1 | name: 💡 Suggest new type
 2 | description: '​‌‍⁠ ' # Magic whitespace to hide this required field
 3 | labels: 'type addition'
 4 | 
 5 | body:
 6 |   - type: textarea
 7 |     id: description
 8 |     validations:
 9 |       required: true
10 |     attributes:
11 |       label: Type description + examples
12 | 
13 |   - type: textarea
14 |     id: type
15 |     attributes:
16 |       label: Type source
17 |       description: If you already have the type source, enter it here as a starting point for a the discussion
18 | 
19 |   - id: requirements
20 |     type: checkboxes
21 |     attributes:
22 |       label: Search existing types and issues first
23 |       options:
24 |         - label: I tried my best to look for it
25 |           required: true
26 | 


--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/2 bug report.yml:
--------------------------------------------------------------------------------
 1 | name: 🐛 Report bug
 2 | description: '​‌‍⁠ ' # Magic whitespace to hide this required field
 3 | labels: bug
 4 | 
 5 | body:
 6 |   - type: textarea
 7 |     id: description
 8 |     validations:
 9 |       required: true
10 |     attributes:
11 |       label: Bug description
12 | 
13 |   - type: input
14 |     id: repro
15 |     validations:
16 |       required: true
17 |     attributes:
18 |       label: Repro
19 |       description: |
20 |         Open [this playground](https://www.typescriptlang.org/play/?#code/JYWwDg9gTgLgBDAnmApnA3gUQB4GMVgwC+cAZlBCHAORKoC0pKAzjNQNwCwAUD3WgDEIEOAF4MPAJABXAHbBc0WQC44rKMFkBzLt0lQAhpoBGEAO6rTEADYoDs3UV19kaAHIQASkdmmzYuBx8QgAeIQgAGhpDE3NqAD5dOGS4AHpUuAA9AH4eIA), write a piece of code that fails your expectations, click "Share", and paste the URL here
21 | 


--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/3 enhancement.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: ♻️ Propose change or improvement to existing types
3 | about: '​‌‍⁠ ' # Magic whitespace to hide this required field
4 | labels: 'enhancement'
5 | ---
6 | 


--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
 1 | version: 2
 2 | updates:
 3 |   - package-ecosystem: 'github-actions'
 4 |     directory: '/'
 5 |     schedule:
 6 |       interval: 'weekly'
 7 |     groups:
 8 |       github-actions:
 9 |         patterns:
10 |           - '*'
11 |   - package-ecosystem: 'npm'
12 |     directory: '/'
13 |     schedule:
14 |       interval: 'monthly'
15 |     versioning-strategy: 'increase-if-necessary'
16 |     groups:
17 |       development-dependencies:
18 |         dependency-type: 'development'
19 | 


--------------------------------------------------------------------------------
/.github/funding.yml:
--------------------------------------------------------------------------------
1 | github: [sindresorhus, som-sm, Emiyaaaaa, voxpelli]
2 | 


--------------------------------------------------------------------------------
/.github/pull_request_template.md:
--------------------------------------------------------------------------------
1 | <!--
2 | 
3 | Thanks for submitting a pull request 🙌
4 | 
5 | If you're submitting a new type, please review the contribution guidelines:
6 | https://github.com/sindresorhus/type-fest/blob/main/.github/contributing.md
7 | 
8 | -->
9 | 


--------------------------------------------------------------------------------
/.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 | 


--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
 1 | name: CI
 2 | on:
 3 |   push:
 4 |     branches:
 5 |       - main
 6 |     tags:
 7 |       - '*'
 8 |   pull_request:
 9 |     branches:
10 |       - main
11 | jobs:
12 |   test:
13 |     name: Node.js ${{ matrix.node-version }}
14 |     runs-on: ubuntu-latest
15 |     strategy:
16 |       fail-fast: false
17 |       matrix:
18 |         node-version:
19 |           - 24
20 |           - 22
21 |           - 20
22 |     steps:
23 |       - uses: actions/checkout@v4
24 |       - uses: actions/setup-node@v4
25 |         with:
26 |           node-version: ${{ matrix.node-version }}
27 |       - run: npm install
28 |       - run: npm test
29 |   types:
30 |     name: TypeScript ${{ matrix.typescript-version }}
31 |     runs-on: ubuntu-latest
32 |     strategy:
33 |       fail-fast: false
34 |       matrix:
35 |         typescript-version:
36 |           - 'latest'
37 |           - '~5.8.0'
38 |     steps:
39 |       - uses: actions/checkout@v4
40 |       - uses: actions/setup-node@v4
41 |         with:
42 |           node-version: 20
43 |       - run: npm install
44 |       - run: npm install typescript@${{ matrix.typescript-version }}
45 |       - run: npx tsc
46 |   test-export:
47 |     name: Test Module Export
48 |     runs-on: ubuntu-latest
49 |     steps:
50 |       - uses: actions/checkout@v4
51 |       - uses: actions/setup-node@v4
52 |         with:
53 |           node-version: 20
54 |       - run: npm install rollup rollup-plugin-dts
55 |       - run: npx rollup index.d.ts -p rollup-plugin-dts -d temp
56 | 


--------------------------------------------------------------------------------
/.github/workflows/ts-canary.yml:
--------------------------------------------------------------------------------
 1 | name: TypeScript Canary
 2 | on:
 3 |   schedule:
 4 |     # Every Thursday at 21.15
 5 |     - cron: '15 21 * * 4'
 6 |   workflow_dispatch:
 7 | jobs:
 8 |   types:
 9 |     name: TypeScript ${{ matrix.typescript-version }}
10 |     runs-on: ubuntu-latest
11 |     strategy:
12 |       fail-fast: false
13 |       matrix:
14 |         typescript-version:
15 |           - next
16 |           - latest
17 |     steps:
18 |       - uses: actions/checkout@v4
19 |       - uses: actions/setup-node@v4
20 |         with:
21 |           node-version: lts/*
22 |       - run: npm install
23 |       - run: npm install typescript@${{ matrix.typescript-version }}
24 |       - name: show installed typescript version
25 |         run: npm list typescript --depth=0
26 |       - run: npx tsc
27 | 


--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | yarn.lock
3 | 


--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | package-lock=false
2 | 


--------------------------------------------------------------------------------
/license-mit:
--------------------------------------------------------------------------------
 1 | MIT License
 2 | 
 3 | Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (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 | 


--------------------------------------------------------------------------------
/lint-rules/import-path.js:
--------------------------------------------------------------------------------
 1 | import path from 'node:path';
 2 | 
 3 | export const importPathRule = /** @type {const} */ ({
 4 | 	meta: {
 5 | 		type: 'problem',
 6 | 		docs: {
 7 | 			description: 'Enforces import paths to end with a \'.d.ts\' extension.',
 8 | 		},
 9 | 		fixable: 'code',
10 | 		messages: {
11 | 			incorrectImportPath:
12 |                 'Import path \'{{importPath}}\' must end with a \'.d.ts\' extension. Use \'{{fixedImportPath}}\' instead.',
13 | 		},
14 | 		schema: [],
15 | 	},
16 | 	defaultOptions: [],
17 | 	create(context) {
18 | 		return {
19 | 			ImportDeclaration(node) {
20 | 				const importPath = node.source.value;
21 | 
22 | 				// Skip if not relative path
23 | 				if (!(importPath.startsWith('./') || importPath.startsWith('../'))) {
24 | 					return;
25 | 				}
26 | 
27 | 				const filename = path.basename(importPath);
28 | 				const firstDotIndex = filename.indexOf('.');
29 | 				const extension = firstDotIndex === -1 ? '' : filename.slice(firstDotIndex);
30 | 
31 | 				// Skip if the import path already ends with `.d.ts`
32 | 				if (extension === '.d.ts') {
33 | 					return;
34 | 				}
35 | 
36 | 				const importPathWithoutExtension = extension.length > 0
37 | 					? importPath.slice(0, -extension.length)
38 | 					: importPath;
39 | 				const fixedImportPath = `${importPathWithoutExtension}.d.ts`;
40 | 
41 | 				context.report({
42 | 					node: node.source,
43 | 					messageId: 'incorrectImportPath',
44 | 					fix(fixer) {
45 | 						return fixer.replaceText(node.source, `'${fixedImportPath}'`);
46 | 					},
47 | 					data: {importPath, fixedImportPath},
48 | 				});
49 | 			},
50 | 		};
51 | 	},
52 | });
53 | 


--------------------------------------------------------------------------------
/lint-rules/source-files-extension.js:
--------------------------------------------------------------------------------
 1 | import path from 'node:path';
 2 | 
 3 | export const sourceFilesExtensionRule = /** @type {const} */ ({
 4 | 	meta: {
 5 | 		type: 'problem',
 6 | 		docs: {
 7 | 			description: 'Enforces source files to end with a \'.d.ts\' extension.',
 8 | 		},
 9 | 		fixable: 'code',
10 | 		messages: {
11 | 			incorrectFilename:
12 | 				'Filename \'{{filename}}\' must end with a \'.d.ts\' extension. Use \'{{fixedFilename}}\' instead.',
13 | 		},
14 | 		schema: [],
15 | 	},
16 | 	defaultOptions: [],
17 | 	create(context) {
18 | 		const filename = path.basename(context.filename);
19 | 		const firstDotIndex = filename.indexOf('.');
20 | 		const extension = firstDotIndex === -1 ? '' : filename.slice(firstDotIndex);
21 | 
22 | 		if (extension === '.d.ts') {
23 | 			return {};
24 | 		}
25 | 
26 | 		return {
27 | 			Program(node) {
28 | 				const filenameWithoutExtension = extension.length > 0
29 | 					? filename.slice(0, -extension.length)
30 | 					: filename;
31 | 				const fixedFilename = `${filenameWithoutExtension}.d.ts`;
32 | 
33 | 				context.report({
34 | 					loc: {column: 0, line: 1}, // Report error on start of the file
35 | 					node,
36 | 					messageId: 'incorrectFilename',
37 | 					data: {filename, fixedFilename},
38 | 				});
39 | 			},
40 | 		};
41 | 	},
42 | });
43 | 


--------------------------------------------------------------------------------
/media/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sindresorhus/type-fest/4d7cc50fbec6ae631fca98ae8d7e498f0d5f61ab/media/logo.png


--------------------------------------------------------------------------------
/media/logo.sketch:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sindresorhus/type-fest/4d7cc50fbec6ae631fca98ae8d7e498f0d5f61ab/media/logo.sketch


--------------------------------------------------------------------------------
/media/logo@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sindresorhus/type-fest/4d7cc50fbec6ae631fca98ae8d7e498f0d5f61ab/media/logo@2x.png


--------------------------------------------------------------------------------
/media/readme.md:
--------------------------------------------------------------------------------
1 | # Media
2 | 
3 | ## Attribution
4 | 
5 | ### Fireworks vector graphic
6 | 
7 | [Free Vectors via Vecteezy!](https://www.vecteezy.com)
8 | 


--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
 1 | {
 2 | 	"name": "type-fest",
 3 | 	"version": "4.41.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 | 	"type": "module",
14 | 	"exports": {
15 | 		".": {
16 | 			"types": "./index.d.ts"
17 | 		},
18 | 		"./globals": {
19 | 			"types": "./source/globals/index.d.ts"
20 | 		}
21 | 	},
22 | 	"types": "./index.d.ts",
23 | 	"sideEffects": false,
24 | 	"engines": {
25 | 		"node": ">=20"
26 | 	},
27 | 	"scripts": {
28 | 		"test:tsc": "tsc",
29 | 		"test:tsd": "tsd",
30 | 		"test:xo": "xo",
31 | 		"test": "run-p test:*"
32 | 	},
33 | 	"files": [
34 | 		"index.d.ts",
35 | 		"source",
36 | 		"license-mit",
37 | 		"license-cc0"
38 | 	],
39 | 	"keywords": [
40 | 		"typescript",
41 | 		"ts",
42 | 		"types",
43 | 		"utility",
44 | 		"util",
45 | 		"utilities",
46 | 		"omit",
47 | 		"merge",
48 | 		"json",
49 | 		"generics"
50 | 	],
51 | 	"dependencies": {
52 | 		"tagged-tag": "^1.0.0"
53 | 	},
54 | 	"devDependencies": {
55 | 		"@sindresorhus/tsconfig": "^7.0.0",
56 | 		"expect-type": "^1.2.1",
57 | 		"npm-run-all2": "^8.0.1",
58 | 		"tsd": "^0.32.0",
59 | 		"typescript": "~5.8.3",
60 | 		"xo": "^1.0.5"
61 | 	},
62 | 	"tsd": {
63 | 		"compilerOptions": {
64 | 			"noUnusedLocals": false
65 | 		}
66 | 	}
67 | }
68 | 


--------------------------------------------------------------------------------
/source/array-indices.d.ts:
--------------------------------------------------------------------------------
 1 | /**
 2 | Provides valid indices for a constant array or tuple.
 3 | 
 4 | Use-case: This type is useful when working with constant arrays or tuples and you want to enforce type-safety for accessing elements by their indices.
 5 | 
 6 | @example
 7 | ```
 8 | import type {ArrayIndices, ArrayValues} from 'type-fest';
 9 | 
10 | const weekdays = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'] as const;
11 | 
12 | type Weekday = ArrayIndices<typeof weekdays>;
13 | type WeekdayName = ArrayValues<typeof weekdays>;
14 | 
15 | const getWeekdayName = (day: Weekday): WeekdayName => weekdays[day];
16 | ```
17 | 
18 | @see {@link ArrayValues}
19 | 
20 | @category Array
21 | */
22 | export type ArrayIndices<Element extends readonly unknown[]> =
23 | 	Exclude<Partial<Element>['length'], Element['length']>;
24 | 


--------------------------------------------------------------------------------
/source/array-values.d.ts:
--------------------------------------------------------------------------------
 1 | /**
 2 | Provides all values for a constant array or tuple.
 3 | 
 4 | Use-case: This type is useful when working with constant arrays or tuples and you want to enforce type-safety with their values.
 5 | 
 6 | @example
 7 | ```
 8 | import type {ArrayValues, ArrayIndices} from 'type-fest';
 9 | 
10 | const weekdays = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'] as const;
11 | 
12 | type WeekdayName = ArrayValues<typeof weekdays>;
13 | type Weekday = ArrayIndices<typeof weekdays>;
14 | 
15 | const getWeekdayName = (day: Weekday): WeekdayName => weekdays[day];
16 | ```
17 | 
18 | @see {@link ArrayIndices}
19 | 
20 | @category Array
21 | */
22 | export type ArrayValues<T extends readonly unknown[]> = T[number];
23 | 


--------------------------------------------------------------------------------
/source/arrayable.d.ts:
--------------------------------------------------------------------------------
 1 | /**
 2 | Create a type that represents either the value or an array of the value.
 3 | 
 4 | @see Promisable
 5 | 
 6 | @example
 7 | ```
 8 | import type {Arrayable} from 'type-fest';
 9 | 
10 | function bundle(input: string, output: Arrayable<string>) {
11 | 	const outputList = Array.isArray(output) ? output : [output];
12 | 
13 | 	// …
14 | 
15 | 	for (const output of outputList) {
16 | 		console.log(`write to: ${output}`);
17 | 	}
18 | }
19 | 
20 | bundle('src/index.js', 'dist/index.js');
21 | bundle('src/index.js', ['dist/index.cjs', 'dist/index.mjs']);
22 | ```
23 | 
24 | @category Array
25 | */
26 | export type Arrayable<T> =
27 | 	T
28 | // TODO: Use `readonly T[]` when this issue is resolved: https://github.com/microsoft/TypeScript/issues/17002
29 | 	| T[];
30 | 


--------------------------------------------------------------------------------
/source/async-return-type.d.ts:
--------------------------------------------------------------------------------
 1 | type AsyncFunction = (...arguments_: any[]) => PromiseLike<unknown>;
 2 | 
 3 | /**
 4 | Unwrap the return type of a function that returns a `Promise`.
 5 | 
 6 | There has been [discussion](https://github.com/microsoft/TypeScript/pull/35998) about implementing this type in TypeScript.
 7 | 
 8 | @example
 9 | ```ts
10 | import type {AsyncReturnType} from 'type-fest';
11 | import {asyncFunction} from 'api';
12 | 
13 | // This type resolves to the unwrapped return type of `asyncFunction`.
14 | type Value = AsyncReturnType<typeof asyncFunction>;
15 | 
16 | async function doSomething(value: Value) {}
17 | 
18 | asyncFunction().then(value => doSomething(value));
19 | ```
20 | 
21 | @category Async
22 | */
23 | export type AsyncReturnType<Target extends AsyncFunction> = Awaited<ReturnType<Target>>;
24 | 


--------------------------------------------------------------------------------
/source/asyncify.d.ts:
--------------------------------------------------------------------------------
 1 | import type {SetReturnType} from './set-return-type.d.ts';
 2 | 
 3 | /**
 4 | Create an async version of the given function type, by boxing the return type in `Promise` while keeping the same parameter types.
 5 | 
 6 | Use-case: You have two functions, one synchronous and one asynchronous that do the same thing. Instead of having to duplicate the type definition, you can use `Asyncify` to reuse the synchronous type.
 7 | 
 8 | @example
 9 | ```
10 | import type {Asyncify} from 'type-fest';
11 | 
12 | // Synchronous function.
13 | function getFooSync(someArg: SomeType): Foo {
14 | 	// …
15 | }
16 | 
17 | type AsyncifiedFooGetter = Asyncify<typeof getFooSync>;
18 | //=> type AsyncifiedFooGetter = (someArg: SomeType) => Promise<Foo>;
19 | 
20 | // Same as `getFooSync` but asynchronous.
21 | const getFooAsync: AsyncifiedFooGetter = (someArg) => {
22 | 	// TypeScript now knows that `someArg` is `SomeType` automatically.
23 | 	// It also knows that this function must return `Promise<Foo>`.
24 | 	// If you have `@typescript-eslint/promise-function-async` linter rule enabled, it will even report that "Functions that return promises must be async.".
25 | 
26 | 	// …
27 | }
28 | ```
29 | 
30 | @category Async
31 | */
32 | export type Asyncify<Function_ extends (...arguments_: any[]) => any> = SetReturnType<Function_, Promise<Awaited<ReturnType<Function_>>>>;
33 | 


--------------------------------------------------------------------------------
/source/basic.d.ts:
--------------------------------------------------------------------------------
 1 | /**
 2 | Matches a [`class`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes).
 3 | 
 4 | @category Class
 5 | */
 6 | export type Class<T, Arguments extends unknown[] = any[]> = {
 7 | 	prototype: Pick<T, keyof T>;
 8 | 	new(...arguments_: Arguments): T;
 9 | };
10 | 
11 | /**
12 | Matches a [`class` constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes).
13 | 
14 | @category Class
15 | */
16 | export type Constructor<T, Arguments extends unknown[] = any[]> = new(...arguments_: Arguments) => T;
17 | 
18 | /**
19 | Matches an [`abstract class`](https://www.typescriptlang.org/docs/handbook/2/classes.html#abstract-classes-and-members).
20 | 
21 | @category Class
22 | 
23 | @privateRemarks
24 | We cannot use a `type` here because TypeScript throws: 'abstract' modifier cannot appear on a type member. (1070)
25 | */
26 | // eslint-disable-next-line @typescript-eslint/consistent-type-definitions
27 | export interface AbstractClass<T, Arguments extends unknown[] = any[]> extends AbstractConstructor<T, Arguments> {
28 | 	prototype: Pick<T, keyof T>;
29 | }
30 | 
31 | /**
32 | Matches an [`abstract class`](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-2.html#abstract-construct-signatures) constructor.
33 | 
34 | @category Class
35 | */
36 | export type AbstractConstructor<T, Arguments extends unknown[] = any[]> = abstract new(...arguments_: Arguments) => T;
37 | 


--------------------------------------------------------------------------------
/source/camel-cased-properties.d.ts:
--------------------------------------------------------------------------------
 1 | import type {CamelCase, CamelCaseOptions, DefaultCamelCaseOptions} from './camel-case.d.ts';
 2 | import type {ApplyDefaultOptions} from './internal/index.d.ts';
 3 | 
 4 | /**
 5 | Convert object properties to camel case but not recursively.
 6 | 
 7 | This can be useful when, for example, converting some API types from a different style.
 8 | 
 9 | @see CamelCasedPropertiesDeep
10 | @see CamelCase
11 | 
12 | @example
13 | ```
14 | import type {CamelCasedProperties} from 'type-fest';
15 | 
16 | interface User {
17 | 	UserId: number;
18 | 	UserName: string;
19 | }
20 | 
21 | const result: CamelCasedProperties<User> = {
22 | 	userId: 1,
23 | 	userName: 'Tom',
24 | };
25 | 
26 | const preserveConsecutiveUppercase: CamelCasedProperties<{fooBAR: string}, {preserveConsecutiveUppercase: true}> = {
27 | 	fooBAR: 'string',
28 | };
29 | ```
30 | 
31 | @category Change case
32 | @category Template literal
33 | @category Object
34 | */
35 | export type CamelCasedProperties<Value, Options extends CamelCaseOptions = {}> = Value extends Function
36 | 	? Value
37 | 	: Value extends Array<infer U>
38 | 		? Value
39 | 		: {
40 | 			[K in keyof Value as
41 | 			CamelCase<K, ApplyDefaultOptions<CamelCaseOptions, DefaultCamelCaseOptions, Options>>
42 | 			]: Value[K];
43 | 		};
44 | 


--------------------------------------------------------------------------------
/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<Awesome, Primitive>;
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<Example, string>;
37 | //=> {b: string | number; c: () => void; d: {}}
38 | ```
39 | 
40 | @category Object
41 | */
42 | export type ConditionalExcept<Base, Condition> = Except<
43 | 	Base,
44 | 	ConditionalKeys<Base, Condition>
45 | >;
46 | 


--------------------------------------------------------------------------------
/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<Awesome, Primitive>;
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<Example, string>;
36 | //=> {a: string}
37 | ```
38 | 
39 | @category Object
40 | */
41 | export type ConditionalPick<Base, Condition> = Pick<
42 | 	Base,
43 | 	ConditionalKeys<Base, Condition>
44 | >;
45 | 


--------------------------------------------------------------------------------
/source/conditional-simplify-deep.d.ts:
--------------------------------------------------------------------------------
 1 | /**
 2 | Recursively simplifies a type while including and/or excluding certain types from being simplified.
 3 | 
 4 | @example
 5 | ```
 6 | import type {ConditionalSimplifyDeep} from 'type-fest';
 7 | 
 8 | type TypeA = {
 9 | 	foo: {
10 | 		a: string;
11 | 	};
12 | };
13 | 
14 | type TypeB = {
15 | 	foo: {
16 | 		b: string;
17 | 	};
18 | };
19 | 
20 | type SimplifyDeepTypeAB = ConditionalSimplifyDeep<TypeA & TypeB, never, object>;
21 | //=> {foo: {a: string; b: string}}
22 | ```
23 | 
24 | @example
25 | ```
26 | import type {ConditionalSimplifyDeep} from 'type-fest';
27 | 
28 | type SomeComplexType1 = {
29 | 	a1: string;
30 | 	b1: number;
31 | 	c1: boolean;
32 | };
33 | 
34 | type SomeComplexType2 = {
35 | 	a2: string;
36 | 	b2: number;
37 | 	c2: boolean;
38 | };
39 | 
40 | type TypeA = {
41 | 	foo: {
42 | 		a: string;
43 | 		complexType: SomeComplexType1;
44 | 	};
45 | };
46 | 
47 | type TypeB = {
48 | 	foo: {
49 | 		b: string;
50 | 		complexType: SomeComplexType2;
51 | 	};
52 | };
53 | 
54 | type SimplifyDeepTypeAB = ConditionalSimplifyDeep<TypeA & TypeB, SomeComplexType1 | SomeComplexType2, object>;
55 | //=> {
56 | //	foo: {
57 | // 		a: string;
58 | // 		b: string;
59 | // 		complexType: SomeComplexType1 & SomeComplexType2;
60 | //	};
61 | // }
62 | ```
63 | 
64 | @see SimplifyDeep
65 | @category Object
66 | */
67 | export type ConditionalSimplifyDeep<Type, ExcludeType = never, IncludeType = unknown> = Type extends ExcludeType
68 | 	? Type
69 | 	: Type extends IncludeType
70 | 		? {[TypeKey in keyof Type]: ConditionalSimplifyDeep<Type[TypeKey], ExcludeType, IncludeType>}
71 | 		: Type;
72 | 


--------------------------------------------------------------------------------
/source/conditional-simplify.d.ts:
--------------------------------------------------------------------------------
 1 | /**
 2 | Simplifies a type while including and/or excluding certain types from being simplified.
 3 | 
 4 | Useful to improve type hints shown in editors. And also to transform an `interface` into a `type` to aid with assignability.
 5 | 
 6 | @example
 7 | ```
 8 | import type {ConditionalSimplify} from 'type-fest';
 9 | 
10 | type TypeA = {
11 | 	a: string;
12 | };
13 | 
14 | type TypeB = {
15 | 	b: string;
16 | };
17 | 
18 | type TypeAB = TypeA & TypeB;
19 | //=> TypeA & TypeB
20 | 
21 | type SimplifyTypeAB = ConditionalSimplify<TypeAB, never, object>;
22 | //=> {a: string; b: string}
23 | ```
24 | 
25 | @example
26 | ```
27 | import type {ConditionalSimplify} from 'type-fest';
28 | 
29 | type Simplify<T> = ConditionalSimplify<T, Set<unknown> | Map<unknown, unknown> | unknown[], object>;
30 | 
31 | type A = Simplify<Set<number> & Set<string>>;
32 | //=> Set<number> & Set<string>
33 | 
34 | type B = Simplify<Map<number, number> & Map<string, string>>;
35 | //=> Map<number, number> & Map<string, string>
36 | 
37 | type C = Simplify<{a: number} & {b: string}>;
38 | //=> {a: number; b: string}
39 | ```
40 | 
41 | @see ConditionalSimplifyDeep
42 | @category Object
43 | */
44 | export type ConditionalSimplify<Type, ExcludeType = never, IncludeType = unknown> = Type extends ExcludeType
45 | 	? Type
46 | 	: Type extends IncludeType
47 | 		? {[TypeKey in keyof Type]: Type[TypeKey]}
48 | 		: Type;
49 | 


--------------------------------------------------------------------------------
/source/delimiter-cased-properties.d.ts:
--------------------------------------------------------------------------------
 1 | import type {DefaultDelimiterCaseOptions, DelimiterCase} from './delimiter-case.d.ts';
 2 | import type {ApplyDefaultOptions} from './internal/index.d.ts';
 3 | import type {WordsOptions} from './words.d.ts';
 4 | 
 5 | /**
 6 | Convert object properties to delimiter case but not recursively.
 7 | 
 8 | This can be useful when, for example, converting some API types from a different style.
 9 | 
10 | @see DelimiterCase
11 | @see DelimiterCasedPropertiesDeep
12 | 
13 | @example
14 | ```
15 | import type {DelimiterCasedProperties} from 'type-fest';
16 | 
17 | interface User {
18 | 	userId: number;
19 | 	userName: string;
20 | }
21 | 
22 | const result: DelimiterCasedProperties<User, '-'> = {
23 | 	'user-id': 1,
24 | 	'user-name': 'Tom',
25 | };
26 | 
27 | const splitOnNumbers: DelimiterCasedProperties<{line1: string}, '-', {splitOnNumbers: true}> = {
28 | 	'line-1': 'string',
29 | };
30 | ```
31 | 
32 | @category Change case
33 | @category Template literal
34 | @category Object
35 | */
36 | export type DelimiterCasedProperties<
37 | 	Value,
38 | 	Delimiter extends string,
39 | 	Options extends WordsOptions = {},
40 | > = Value extends Function
41 | 	? Value
42 | 	: Value extends Array<infer U>
43 | 		? Value
44 | 		: {[K in keyof Value as
45 | 			DelimiterCase<K, Delimiter, ApplyDefaultOptions<WordsOptions, DefaultDelimiterCaseOptions, Options>>
46 | 			]: Value[K]};
47 | 


--------------------------------------------------------------------------------
/source/empty-object.d.ts:
--------------------------------------------------------------------------------
 1 | declare const emptyObjectSymbol: unique symbol;
 2 | 
 3 | /**
 4 | Represents a strictly empty plain object, the `{}` value.
 5 | 
 6 | When you annotate something as the type `{}`, it can be anything except `null` and `undefined`. This means that you cannot use `{}` to represent an empty plain object ([read more](https://stackoverflow.com/questions/47339869/typescript-empty-object-and-any-difference/52193484#52193484)).
 7 | 
 8 | @example
 9 | ```
10 | import type {EmptyObject} from 'type-fest';
11 | 
12 | // The following illustrates the problem with `{}`.
13 | const foo1: {} = {}; // Pass
14 | const foo2: {} = []; // Pass
15 | const foo3: {} = 42; // Pass
16 | const foo4: {} = {a: 1}; // Pass
17 | 
18 | // With `EmptyObject` only the first case is valid.
19 | const bar1: EmptyObject = {}; // Pass
20 | const bar2: EmptyObject = 42; // Fail
21 | const bar3: EmptyObject = []; // Fail
22 | const bar4: EmptyObject = {a: 1}; // Fail
23 | ```
24 | 
25 | Unfortunately, `Record<string, never>`, `Record<keyof any, never>` and `Record<never, never>` do not work. See {@link https://github.com/sindresorhus/type-fest/issues/395 #395}.
26 | 
27 | @category Object
28 | */
29 | export type EmptyObject = {[emptyObjectSymbol]?: never};
30 | 
31 | /**
32 | Returns a `boolean` for whether the type is strictly equal to an empty plain object, the `{}` value.
33 | 
34 | @example
35 | ```
36 | import type {IsEmptyObject} from 'type-fest';
37 | 
38 | type Pass = IsEmptyObject<{}>; //=> true
39 | type Fail = IsEmptyObject<[]>; //=> false
40 | type Fail = IsEmptyObject<null>; //=> false
41 | ```
42 | 
43 | @see EmptyObject
44 | @category Object
45 | */
46 | export type IsEmptyObject<T> = T extends EmptyObject ? true : false;
47 | 


--------------------------------------------------------------------------------
/source/enforce-optional.d.ts:
--------------------------------------------------------------------------------
 1 | import type {Simplify} from './simplify.d.ts';
 2 | 
 3 | // Returns `never` if the key is optional otherwise return the key type.
 4 | type RequiredFilter<Type, Key extends keyof Type> = undefined extends Type[Key]
 5 | 	? Type[Key] extends undefined
 6 | 		? Key
 7 | 		: never
 8 | 	: Key;
 9 | 
10 | // Returns `never` if the key is required otherwise return the key type.
11 | type OptionalFilter<Type, Key extends keyof Type> = undefined extends Type[Key]
12 | 	? Type[Key] extends undefined
13 | 		? never
14 | 		: Key
15 | 	: never;
16 | 
17 | /**
18 | Enforce optional keys (by adding the `?` operator) for keys that have a union with `undefined`.
19 | 
20 | @example
21 | ```
22 | import type {EnforceOptional} from 'type-fest';
23 | 
24 | type Foo = {
25 | 	a: string;
26 | 	b?: string;
27 | 	c: undefined;
28 | 	d: number | undefined;
29 | };
30 | 
31 | type FooBar = EnforceOptional<Foo>;
32 | // => {
33 | // 	a: string;
34 | // 	b?: string;
35 | // 	c: undefined;
36 | // 	d?: number;
37 | // }
38 | ```
39 | 
40 | @internal
41 | @category Object
42 | */
43 | export type EnforceOptional<ObjectType> = Simplify<{
44 | 	[Key in keyof ObjectType as RequiredFilter<ObjectType, Key>]: ObjectType[Key]
45 | } & {
46 | 	[Key in keyof ObjectType as OptionalFilter<ObjectType, Key>]?: Exclude<ObjectType[Key], undefined>
47 | }>;
48 | 


--------------------------------------------------------------------------------
/source/extends-strict.d.ts:
--------------------------------------------------------------------------------
 1 | import type {IsNever} from './is-never.d.ts';
 2 | import type {IsAny} from './is-any.d.ts';
 3 | 
 4 | /**
 5 | A stricter, non-distributive version of `extends` for checking whether one type is assignable to another.
 6 | 
 7 | Unlike the built-in `extends` keyword, `ExtendsStrict`:
 8 | 
 9 | 1. Prevents distribution over union types by wrapping both types in tuples. For example, `ExtendsStrict<string | number, number>` returns `false`, whereas `string | number extends number` would result in `boolean`.
10 | 
11 | 2. Treats `never` as a special case: `never` doesn't extend every other type, it only extends itself (or `any`). For example, `ExtendsStrict<never, number>` returns `false` whereas `never extends number` would result in `true`.
12 | 
13 | @example
14 | ```
15 | import type {ExtendsStrict} from 'type-fest';
16 | 
17 | type T1 = ExtendsStrict<number | string, string>;
18 | //=> false
19 | 
20 | type T2 = ExtendsStrict<never, number>;
21 | //=> false
22 | 
23 | type T3 = ExtendsStrict<never, never>;
24 | //=> true
25 | 
26 | type T4 = ExtendsStrict<string, number | string>;
27 | //=> true
28 | 
29 | type T5 = ExtendsStrict<string, string>;
30 | //=> true
31 | ```
32 | 
33 | @category Improved Built-in
34 | */
35 | export type ExtendsStrict<Left, Right> =
36 | 	IsAny<Left | Right> extends true
37 | 		? true
38 | 		: IsNever<Left> extends true
39 | 			? IsNever<Right>
40 | 			: [Left] extends [Right]
41 | 				? true
42 | 				: false;
43 | 


--------------------------------------------------------------------------------
/source/global-this.d.ts:
--------------------------------------------------------------------------------
 1 | /**
 2 | Declare locally scoped properties on `globalThis`.
 3 | 
 4 | When defining a global variable in a declaration file is inappropriate, it can be helpful to define a `type` or `interface` (say `ExtraGlobals`) with the global variable and then cast `globalThis` via code like `globalThis as unknown as ExtraGlobals`.
 5 | 
 6 | Instead of casting through `unknown`, you can update your `type` or `interface` to extend `GlobalThis` and then directly cast `globalThis`.
 7 | 
 8 | @example
 9 | ```
10 | import type {GlobalThis} from 'type-fest';
11 | 
12 | type ExtraGlobals = GlobalThis & {
13 | 	readonly GLOBAL_TOKEN: string;
14 | };
15 | 
16 | (globalThis as ExtraGlobals).GLOBAL_TOKEN;
17 | ```
18 | 
19 | @category Type
20 | */
21 | export type GlobalThis = typeof globalThis;
22 | 


--------------------------------------------------------------------------------
/source/globals/index.d.ts:
--------------------------------------------------------------------------------
1 | export type * from './observable-like.d.ts';
2 | 


--------------------------------------------------------------------------------
/source/greater-than-or-equal.d.ts:
--------------------------------------------------------------------------------
 1 | import type {GreaterThan} from './greater-than.d.ts';
 2 | 
 3 | /**
 4 | Returns a boolean for whether a given number is greater than or equal to another number.
 5 | 
 6 | @example
 7 | ```
 8 | import type {GreaterThanOrEqual} from 'type-fest';
 9 | 
10 | GreaterThanOrEqual<1, -5>;
11 | //=> true
12 | 
13 | GreaterThanOrEqual<1, 1>;
14 | //=> true
15 | 
16 | GreaterThanOrEqual<1, 5>;
17 | //=> false
18 | ```
19 | */
20 | export type GreaterThanOrEqual<A extends number, B extends number> = number extends A | B
21 | 	? never
22 | 	: A extends B ? true : GreaterThan<A, B>;
23 | 


--------------------------------------------------------------------------------
/source/has-optional-keys.d.ts:
--------------------------------------------------------------------------------
 1 | import type {OptionalKeysOf} from './optional-keys-of.d.ts';
 2 | 
 3 | /**
 4 | Creates a type that represents `true` or `false` depending on whether the given type has any optional fields.
 5 | 
 6 | This is useful when you want to create an API whose behavior depends on the presence or absence of optional fields.
 7 | 
 8 | @example
 9 | ```
10 | import type {HasOptionalKeys, OptionalKeysOf} from 'type-fest';
11 | 
12 | type UpdateService<Entity extends object> = {
13 | 	removeField: HasOptionalKeys<Entity> extends true
14 | 		? (field: OptionalKeysOf<Entity>) => Promise<void>
15 | 		: never
16 | }
17 | ```
18 | 
19 | @category Utilities
20 | */
21 | export type HasOptionalKeys<BaseType extends object> = OptionalKeysOf<BaseType> extends never ? false : true;
22 | 


--------------------------------------------------------------------------------
/source/has-readonly-keys.d.ts:
--------------------------------------------------------------------------------
 1 | import type {ReadonlyKeysOf} from './readonly-keys-of.d.ts';
 2 | 
 3 | /**
 4 | Creates a type that represents `true` or `false` depending on whether the given type has any readonly fields.
 5 | 
 6 | This is useful when you want to create an API whose behavior depends on the presence or absence of readonly fields.
 7 | 
 8 | @example
 9 | ```
10 | import type {HasReadonlyKeys, ReadonlyKeysOf} from 'type-fest';
11 | 
12 | type UpdateService<Entity extends object> = {
13 | 	removeField: HasReadonlyKeys<Entity> extends true
14 | 		? (field: ReadonlyKeysOf<Entity>) => Promise<void>
15 | 		: never
16 | }
17 | ```
18 | 
19 | @category Utilities
20 | */
21 | export type HasReadonlyKeys<BaseType extends object> = ReadonlyKeysOf<BaseType> extends never ? false : true;
22 | 


--------------------------------------------------------------------------------
/source/has-required-keys.d.ts:
--------------------------------------------------------------------------------
 1 | import type {RequiredKeysOf} from './required-keys-of.d.ts';
 2 | 
 3 | /**
 4 | Creates a type that represents `true` or `false` depending on whether the given type has any required fields.
 5 | 
 6 | This is useful when you want to create an API whose behavior depends on the presence or absence of required fields.
 7 | 
 8 | @example
 9 | ```
10 | import type {HasRequiredKeys} from 'type-fest';
11 | 
12 | type GeneratorOptions<Template extends object> = {
13 | 	prop1: number;
14 | 	prop2: string;
15 | } & (HasRequiredKeys<Template> extends true
16 | 	? {template: Template}
17 | 	: {template?: Template});
18 | 
19 | interface Template1 {
20 | 	optionalSubParam?: string;
21 | }
22 | 
23 | interface Template2 {
24 | 	requiredSubParam: string;
25 | }
26 | 
27 | type Options1 = GeneratorOptions<Template1>;
28 | type Options2 = GeneratorOptions<Template2>;
29 | 
30 | const optA: Options1 = {
31 | 	prop1: 0,
32 | 	prop2: 'hi'
33 | };
34 | const optB: Options1 = {
35 | 	prop1: 0,
36 | 	prop2: 'hi',
37 | 	template: {}
38 | };
39 | const optC: Options1 = {
40 | 	prop1: 0,
41 | 	prop2: 'hi',
42 | 	template: {
43 | 		optionalSubParam: 'optional value'
44 | 	}
45 | };
46 | 
47 | const optD: Options2 = {
48 | 	prop1: 0,
49 | 	prop2: 'hi',
50 | 	template: {
51 | 		requiredSubParam: 'required value'
52 | 	}
53 | };
54 | 
55 | ```
56 | 
57 | @category Utilities
58 | */
59 | export type HasRequiredKeys<BaseType extends object> = RequiredKeysOf<BaseType> extends never ? false : true;
60 | 


--------------------------------------------------------------------------------
/source/has-writable-keys.d.ts:
--------------------------------------------------------------------------------
 1 | import type {WritableKeysOf} from './writable-keys-of.d.ts';
 2 | 
 3 | /**
 4 | Creates a type that represents `true` or `false` depending on whether the given type has any writable fields.
 5 | 
 6 | This is useful when you want to create an API whose behavior depends on the presence or absence of writable fields.
 7 | 
 8 | @example
 9 | ```
10 | import type {HasWritableKeys, WritableKeysOf} from 'type-fest';
11 | 
12 | type UpdateService<Entity extends object> = {
13 | 	removeField: HasWritableKeys<Entity> extends true
14 | 		? (field: WritableKeysOf<Entity>) => Promise<void>
15 | 		: never
16 | }
17 | ```
18 | 
19 | @category Utilities
20 | */
21 | export type HasWritableKeys<BaseType extends object> = WritableKeysOf<BaseType> extends never ? false : true;
22 | 


--------------------------------------------------------------------------------
/source/if-any.d.ts:
--------------------------------------------------------------------------------
 1 | import type {IsAny} from './is-any.d.ts';
 2 | 
 3 | /**
 4 | An if-else-like type that resolves depending on whether the given type is `any`.
 5 | 
 6 | @deprecated This type will be removed in the next major version. Use the {@link If} type instead.
 7 | 
 8 | @see {@link IsAny}
 9 | 
10 | @example
11 | ```
12 | import type {IfAny} from 'type-fest';
13 | 
14 | type ShouldBeTrue = IfAny<any>;
15 | //=> true
16 | 
17 | type ShouldBeBar = IfAny<'not any', 'foo', 'bar'>;
18 | //=> 'bar'
19 | ```
20 | 
21 | @category Type Guard
22 | @category Utilities
23 | */
24 | export type IfAny<T, TypeIfAny = true, TypeIfNotAny = false> = (
25 | 	IsAny<T> extends true ? TypeIfAny : TypeIfNotAny
26 | );
27 | 


--------------------------------------------------------------------------------
/source/if-empty-object.d.ts:
--------------------------------------------------------------------------------
 1 | import type {IsEmptyObject} from './empty-object.d.ts';
 2 | 
 3 | /**
 4 | An if-else-like type that resolves depending on whether the given type is `{}`.
 5 | 
 6 | @deprecated This type will be removed in the next major version. Use the {@link If} type instead.
 7 | 
 8 | @see {@link IsEmptyObject}
 9 | 
10 | @example
11 | ```
12 | import type {IfEmptyObject} from 'type-fest';
13 | 
14 | type ShouldBeTrue = IfEmptyObject<{}>;
15 | //=> true
16 | 
17 | type ShouldBeBar = IfEmptyObject<{key: any}, 'foo', 'bar'>;
18 | //=> 'bar'
19 | ```
20 | 
21 | @category Type Guard
22 | @category Utilities
23 | */
24 | export type IfEmptyObject<
25 | 	T,
26 | 	TypeIfEmptyObject = true,
27 | 	TypeIfNotEmptyObject = false,
28 | > = IsEmptyObject<T> extends true ? TypeIfEmptyObject : TypeIfNotEmptyObject;
29 | 


--------------------------------------------------------------------------------
/source/if-never.d.ts:
--------------------------------------------------------------------------------
 1 | import type {IsNever} from './is-never.d.ts';
 2 | 
 3 | /**
 4 | An if-else-like type that resolves depending on whether the given type is `never`.
 5 | 
 6 | @deprecated This type will be removed in the next major version. Use the {@link If} type instead.
 7 | 
 8 | @see {@link IsNever}
 9 | 
10 | @example
11 | ```
12 | import type {IfNever} from 'type-fest';
13 | 
14 | type ShouldBeTrue = IfNever<never>;
15 | //=> true
16 | 
17 | type ShouldBeBar = IfNever<'not never', 'foo', 'bar'>;
18 | //=> 'bar'
19 | ```
20 | 
21 | @category Type Guard
22 | @category Utilities
23 | */
24 | export type IfNever<T, TypeIfNever = true, TypeIfNotNever = false> = (
25 | 	IsNever<T> extends true ? TypeIfNever : TypeIfNotNever
26 | );
27 | 


--------------------------------------------------------------------------------
/source/if-null.d.ts:
--------------------------------------------------------------------------------
 1 | import type {IsNull} from './is-null.d.ts';
 2 | 
 3 | /**
 4 | An if-else-like type that resolves depending on whether the given type is `null`.
 5 | 
 6 | @deprecated This type will be removed in the next major version. Use the {@link If} type instead.
 7 | 
 8 | @see {@link IsNull}
 9 | 
10 | @example
11 | ```
12 | import type {IfNull} from 'type-fest';
13 | 
14 | type ShouldBeTrue = IfNull<null>;
15 | //=> true
16 | 
17 | type ShouldBeBar = IfNull<'not null', 'foo', 'bar'>;
18 | //=> 'bar'
19 | ```
20 | 
21 | @category Type Guard
22 | @category Utilities
23 | */
24 | export type IfNull<T, TypeIfNull = true, TypeIfNotNull = false> = (
25 | 	IsNull<T> extends true ? TypeIfNull : TypeIfNotNull
26 | );
27 | 


--------------------------------------------------------------------------------
/source/if-unknown.d.ts:
--------------------------------------------------------------------------------
 1 | import type {IsUnknown} from './is-unknown.d.ts';
 2 | 
 3 | /**
 4 | An if-else-like type that resolves depending on whether the given type is `unknown`.
 5 | 
 6 | @deprecated This type will be removed in the next major version. Use the {@link If} type instead.
 7 | 
 8 | @see {@link IsUnknown}
 9 | 
10 | @example
11 | ```
12 | import type {IfUnknown} from 'type-fest';
13 | 
14 | type ShouldBeTrue = IfUnknown<unknown>;
15 | //=> true
16 | 
17 | type ShouldBeBar = IfUnknown<'not unknown', 'foo', 'bar'>;
18 | //=> 'bar'
19 | ```
20 | 
21 | @category Type Guard
22 | @category Utilities
23 | */
24 | export type IfUnknown<T, TypeIfUnknown = true, TypeIfNotUnknown = false> = (
25 | 	IsUnknown<T> extends true ? TypeIfUnknown : TypeIfNotUnknown
26 | );
27 | 


--------------------------------------------------------------------------------
/source/includes.d.ts:
--------------------------------------------------------------------------------
 1 | import type {IsEqual} from './is-equal.d.ts';
 2 | 
 3 | /**
 4 | Returns a boolean for whether the given array includes the given item.
 5 | 
 6 | This can be useful if another type wants to make a decision based on whether the array includes that item.
 7 | 
 8 | @example
 9 | ```
10 | import type {Includes} from 'type-fest';
11 | 
12 | type hasRed<array extends any[]> = Includes<array, 'red'>;
13 | ```
14 | 
15 | @category Array
16 | */
17 | export type Includes<Value extends readonly any[], Item> =
18 | 	Value extends readonly [Value[0], ...infer rest]
19 | 		? IsEqual<Value[0], Item> extends true
20 | 			? true
21 | 			: Includes<rest, Item>
22 | 		: false;
23 | 


--------------------------------------------------------------------------------
/source/int-closed-range.d.ts:
--------------------------------------------------------------------------------
 1 | import type {IntRange} from './int-range.d.ts';
 2 | import type {Sum} from './sum.d.ts';
 3 | 
 4 | /**
 5 | Generate a union of numbers.
 6 | 
 7 | The numbers are created from the given `Start` (inclusive) parameter to the given `End` (inclusive) parameter.
 8 | 
 9 | You skip over numbers using the `Step` parameter (defaults to `1`). For example, `IntClosedRange<0, 10, 2>` will create a union of `0 | 2 | 4 | 6 | 8 | 10`.
10 | 
11 | Note: `Start` or `End` must be non-negative and smaller than `999`.
12 | 
13 | Use-cases:
14 | 1. This can be used to define a set of valid input/output values. for example:
15 | 	```
16 | 	type Age = IntClosedRange<0, 120>; //=> 0 | 1 | 2 | ... | 119 | 120
17 | 	type FontSize = IntClosedRange<10, 20>; //=> 10 | 11 | ... | 19 | 20
18 | 	type EvenNumber = IntClosedRange<0, 10, 2>; //=> 0 | 2 | 4 | 6 | 8 | 10
19 | 	```
20 | 2. This can be used to define random numbers in a range. For example, `type RandomNumber = IntClosedRange<0, 100>;`
21 | 
22 | @example
23 | ```
24 | import type {IntClosedRange} from 'type-fest';
25 | 
26 | // Create union type `0 | 1 | ... | 9`
27 | type ZeroToNine = IntClosedRange<0, 9>;
28 | 
29 | // Create union type `100 | 200 | 300 | ... | 900`
30 | type Hundreds = IntClosedRange<100, 900, 100>;
31 | ```
32 | 
33 | @see IntRange
34 | */
35 | export type IntClosedRange<Start extends number, End extends number, Skip extends number = 1> = IntRange<Start, Sum<End, 1>, Skip>;
36 | 


--------------------------------------------------------------------------------
/source/internal/characters.d.ts:
--------------------------------------------------------------------------------
 1 | export type Whitespace =
 2 | 	| '\u{9}' // '\t'
 3 | 	| '\u{A}' // '\n'
 4 | 	| '\u{B}' // '\v'
 5 | 	| '\u{C}' // '\f'
 6 | 	| '\u{D}' // '\r'
 7 | 	| '\u{20}' // ' '
 8 | 	| '\u{85}'
 9 | 	| '\u{A0}'
10 | 	| '\u{1680}'
11 | 	| '\u{2000}'
12 | 	| '\u{2001}'
13 | 	| '\u{2002}'
14 | 	| '\u{2003}'
15 | 	| '\u{2004}'
16 | 	| '\u{2005}'
17 | 	| '\u{2006}'
18 | 	| '\u{2007}'
19 | 	| '\u{2008}'
20 | 	| '\u{2009}'
21 | 	| '\u{200A}'
22 | 	| '\u{2028}'
23 | 	| '\u{2029}'
24 | 	| '\u{202F}'
25 | 	| '\u{205F}'
26 | 	| '\u{3000}'
27 | 	| '\u{FEFF}';
28 | 
29 | export type WordSeparators = '-' | '_' | Whitespace;
30 | 
31 | export type AsciiPunctuation =
32 | 	| '!'
33 | 	| '"'
34 | 	| '#'
35 | 	| '
#39;
36 | 	| '%'
37 | 	| '&'
38 | 	| '\''
39 | 	| '('
40 | 	| ')'
41 | 	| '*'
42 | 	| '+'
43 | 	| ','
44 | 	| '-'
45 | 	| '.'
46 | 	| '/'
47 | 	| ':'
48 | 	| ';'
49 | 	| '<'
50 | 	| '='
51 | 	| '>'
52 | 	| '?'
53 | 	| '@'
54 | 	| '['
55 | 	| '\\'
56 | 	| ']'
57 | 	| '^'
58 | 	| '_'
59 | 	| '`'
60 | 	| '{'
61 | 	| '|'
62 | 	| '}'
63 | 	| '~';
64 | 


--------------------------------------------------------------------------------
/source/internal/index.d.ts:
--------------------------------------------------------------------------------
1 | export type * from './array.d.ts';
2 | export type * from './characters.d.ts';
3 | export type * from './keys.d.ts';
4 | export type * from './numeric.d.ts';
5 | export type * from './object.d.ts';
6 | export type * from './string.d.ts';
7 | export type * from './tuple.d.ts';
8 | export type * from './type.d.ts';
9 | 


--------------------------------------------------------------------------------
/source/is-any.d.ts:
--------------------------------------------------------------------------------
 1 | /**
 2 | Returns a boolean for whether the given type is `any`.
 3 | 
 4 | @link https://stackoverflow.com/a/49928360/1490091
 5 | 
 6 | Useful in type utilities, such as disallowing `any`s to be passed to a function.
 7 | 
 8 | @example
 9 | ```
10 | import type {IsAny} from 'type-fest';
11 | 
12 | const typedObject = {a: 1, b: 2} as const;
13 | const anyObject: any = {a: 1, b: 2};
14 | 
15 | function get<O extends (IsAny<O> extends true ? {} : Record<string, number>), K extends keyof O = keyof O>(obj: O, key: K) {
16 | 	return obj[key];
17 | }
18 | 
19 | const typedA = get(typedObject, 'a');
20 | //=> 1
21 | 
22 | const anyA = get(anyObject, 'a');
23 | //=> any
24 | ```
25 | 
26 | @category Type Guard
27 | @category Utilities
28 | */
29 | export type IsAny<T> = 0 extends 1 & NoInfer<T> ? true : false;
30 | 


--------------------------------------------------------------------------------
/source/is-equal.d.ts:
--------------------------------------------------------------------------------
 1 | /**
 2 | Returns a boolean for whether the two given types are equal.
 3 | 
 4 | @link https://github.com/microsoft/TypeScript/issues/27024#issuecomment-421529650
 5 | @link https://stackoverflow.com/questions/68961864/how-does-the-equals-work-in-typescript/68963796#68963796
 6 | 
 7 | Use-cases:
 8 | - If you want to make a conditional branch based on the result of a comparison of two types.
 9 | 
10 | @example
11 | ```
12 | import type {IsEqual} from 'type-fest';
13 | 
14 | // This type returns a boolean for whether the given array includes the given item.
15 | // `IsEqual` is used to compare the given array at position 0 and the given item and then return true if they are equal.
16 | type Includes<Value extends readonly any[], Item> =
17 | 	Value extends readonly [Value[0], ...infer rest]
18 | 		? IsEqual<Value[0], Item> extends true
19 | 			? true
20 | 			: Includes<rest, Item>
21 | 		: false;
22 | ```
23 | 
24 | @category Type Guard
25 | @category Utilities
26 | */
27 | export type IsEqual<A, B> =
28 | 	(<G>() => G extends A & G | G ? 1 : 2) extends
29 | 	(<G>() => G extends B & G | G ? 1 : 2)
30 | 		? true
31 | 		: false;
32 | 


--------------------------------------------------------------------------------
/source/is-float.d.ts:
--------------------------------------------------------------------------------
 1 | /**
 2 | Returns a boolean for whether the given number is a float, like `1.5` or `-1.5`.
 3 | 
 4 | Use-case:
 5 | - If you want to make a conditional branch based on the result of whether a number is a float or not.
 6 | 
 7 | @example
 8 | ```
 9 | import type {IsFloat, PositiveInfinity} from 'type-fest';
10 | 
11 | type A = IsFloat<1.5>;
12 | //=> true
13 | 
14 | type B = IsFloat<-1.5>;
15 | //=> true
16 | 
17 | type C = IsFloat<1e-7>;
18 | //=> true
19 | 
20 | type D = IsFloat<1.0>;
21 | //=> false
22 | 
23 | type E = IsFloat<PositiveInfinity>;
24 | //=> false
25 | 
26 | type F = IsFloat<1.23e+21>;
27 | //=> false
28 | ```
29 | 
30 | @category Type Guard
31 | @category Numeric
32 | */
33 | export type IsFloat<T> = T extends number
34 | 	? `${T}` extends `${number}e${infer E extends '-' | '+'}${number}`
35 | 		? E extends '-'
36 | 			? true
37 | 			: false
38 | 		: `${T}` extends `${number}.${number}`
39 | 			? true
40 | 			: false
41 | 	: false;
42 | 


--------------------------------------------------------------------------------
/source/is-integer.d.ts:
--------------------------------------------------------------------------------
 1 | import type {Not} from './internal/index.d.ts';
 2 | import type {IsFloat} from './is-float.d.ts';
 3 | import type {PositiveInfinity, NegativeInfinity} from './numeric.d.ts';
 4 | 
 5 | /**
 6 | Returns a boolean for whether the given number is an integer, like `-5`, `1.0`, or `100`.
 7 | 
 8 | Use-case:
 9 | - If you want to make a conditional branch based on the result of whether a number is an integer or not.
10 | 
11 | @example
12 | ```
13 | import type {IsInteger, PositiveInfinity} from 'type-fest';
14 | 
15 | type A = IsInteger<1>;
16 | //=> true
17 | 
18 | type B = IsInteger<1.0>;
19 | //=> true
20 | 
21 | type C = IsInteger<-1>;
22 | //=> true
23 | 
24 | type D = IsInteger<0b10>;
25 | //=> true
26 | 
27 | type E = IsInteger<0o10>;
28 | //=> true
29 | 
30 | type F = IsInteger<0x10>;
31 | //=> true
32 | 
33 | type G = IsInteger<1.23+21>;
34 | //=> true
35 | 
36 | type H = IsInteger<1.5>;
37 | //=> false
38 | 
39 | type I = IsInteger<PositiveInfinity>;
40 | //=> false
41 | 
42 | type J = IsInteger<1e-7>;
43 | //=> false
44 | ```
45 | 
46 | @category Type Guard
47 | @category Numeric
48 | */
49 | export type IsInteger<T> =
50 | T extends bigint
51 | 	? true
52 | 	: T extends number
53 | 		? number extends T
54 | 			? false
55 | 			: T extends PositiveInfinity | NegativeInfinity
56 | 				? false
57 | 				: Not<IsFloat<T>>
58 | 		: false;
59 | 


--------------------------------------------------------------------------------
/source/is-lowercase.d.ts:
--------------------------------------------------------------------------------
 1 | import type {AllExtend} from './all-extend.d.ts';
 2 | 
 3 | /**
 4 | Returns a boolean for whether the given string literal is lowercase.
 5 | 
 6 | @example
 7 | ```
 8 | import type {IsLowercase} from 'type-fest';
 9 | 
10 | IsLowercase<'abc'>;
11 | //=> true
12 | 
13 | IsLowercase<'Abc'>;
14 | //=> false
15 | 
16 | IsLowercase<string>;
17 | //=> boolean
18 | ```
19 | */
20 | export type IsLowercase<S extends string> = AllExtend<_IsLowercase<S>, true>;
21 | 
22 | /**
23 | Loops through each part in the string and returns a boolean array indicating whether each part is lowercase.
24 | */
25 | type _IsLowercase<S extends string, Accumulator extends boolean[] = []> = S extends `${infer First}${infer Rest}`
26 | 	? _IsLowercase<Rest, [...Accumulator, IsLowercaseHelper<First>]>
27 | 	: [...Accumulator, IsLowercaseHelper<S>];
28 | 
29 | /**
30 | Returns a boolean for whether an individual part of the string is lowercase.
31 | */
32 | type IsLowercaseHelper<S extends string> = S extends Lowercase<string>
33 | 	? true
34 | 	: S extends Uppercase<string> | Capitalize<string> | `${string}${Uppercase<string>}${string}`
35 | 		? false
36 | 		: boolean;
37 | 


--------------------------------------------------------------------------------
/source/is-never.d.ts:
--------------------------------------------------------------------------------
 1 | /**
 2 | Returns a boolean for whether the given type is `never`.
 3 | 
 4 | @link https://github.com/microsoft/TypeScript/issues/31751#issuecomment-498526919
 5 | @link https://stackoverflow.com/a/53984913/10292952
 6 | @link https://www.zhenghao.io/posts/ts-never
 7 | 
 8 | Useful in type utilities, such as checking if something does not occur.
 9 | 
10 | @example
11 | ```
12 | import type {IsNever, And} from 'type-fest';
13 | 
14 | // https://github.com/andnp/SimplyTyped/blob/master/src/types/strings.ts
15 | type AreStringsEqual<A extends string, B extends string> =
16 | 	And<
17 | 		IsNever<Exclude<A, B>> extends true ? true : false,
18 | 		IsNever<Exclude<B, A>> extends true ? true : false
19 | 	>;
20 | 
21 | type EndIfEqual<I extends string, O extends string> =
22 | 	AreStringsEqual<I, O> extends true
23 | 		? never
24 | 		: void;
25 | 
26 | function endIfEqual<I extends string, O extends string>(input: I, output: O): EndIfEqual<I, O> {
27 | 	if (input === output) {
28 | 		process.exit(0);
29 | 	}
30 | }
31 | 
32 | endIfEqual('abc', 'abc');
33 | //=> never
34 | 
35 | endIfEqual('abc', '123');
36 | //=> void
37 | ```
38 | 
39 | @category Type Guard
40 | @category Utilities
41 | */
42 | export type IsNever<T> = [T] extends [never] ? true : false;
43 | 


--------------------------------------------------------------------------------
/source/is-null.d.ts:
--------------------------------------------------------------------------------
 1 | /**
 2 | Returns a boolean for whether the given type is `null`.
 3 | 
 4 | @example
 5 | ```
 6 | import type {IsNull} from 'type-fest';
 7 | 
 8 | type NonNullFallback<T, Fallback> = IsNull<T> extends true ? Fallback : T;
 9 | 
10 | type Example1 = NonNullFallback<null, string>;
11 | //=> string
12 | 
13 | type Example2 = NonNullFallback<number, string>;
14 | //=? number
15 | ```
16 | 
17 | @category Type Guard
18 | @category Utilities
19 | */
20 | export type IsNull<T> = [T] extends [null] ? true : false;
21 | 


--------------------------------------------------------------------------------
/source/is-nullable.d.ts:
--------------------------------------------------------------------------------
 1 | import type {IsAny} from './is-any.d.ts';
 2 | 
 3 | /**
 4 | Returns a boolean for whether the given type includes `null`.
 5 | 
 6 | Note: The built-in `NonNullable` type removes both `null` and `undefined`, which is not accurate for the name.
 7 | 
 8 | @example
 9 | ```ts
10 | import type {IsNullable} from 'type-fest';
11 | 
12 | type A = IsNullable<string>;
13 | //=> false
14 | 
15 | type B = IsNullable<string | null>;
16 | //=> true
17 | 
18 | type C = IsNullable<string | undefined>;
19 | //=> false
20 | 
21 | type D = IsNullable<string | null | undefined>;
22 | //=> true
23 | ```
24 | 
25 | @category Type Guard
26 | @category Utilities
27 | */
28 | export type IsNullable<T> = IsAny<T> extends true ? true : Extract<T, null> extends never ? false : true;
29 | 


--------------------------------------------------------------------------------
/source/is-optional.d.ts:
--------------------------------------------------------------------------------
 1 | import type {IsAny} from './is-any.d.ts';
 2 | 
 3 | /**
 4 | Returns a boolean for whether the given type includes `undefined`.
 5 | 
 6 | @example
 7 | ```ts
 8 | import type {IsOptional} from 'type-fest';
 9 | 
10 | type A = IsOptional<string>;
11 | //=> false
12 | 
13 | type B = IsOptional<string | undefined>;
14 | //=> true
15 | 
16 | type C = IsOptional<string | null>;
17 | //=> false
18 | 
19 | type D = IsOptional<string | null | undefined>;
20 | //=> true
21 | ```
22 | 
23 | @category Type Guard
24 | @category Utilities
25 | */
26 | export type IsOptional<T> = IsAny<T> extends true ? true : Extract<T, undefined> extends never ? false : true;
27 | 


--------------------------------------------------------------------------------
/source/is-union.d.ts:
--------------------------------------------------------------------------------
 1 | import type {IsNever} from './is-never.d.ts';
 2 | 
 3 | /**
 4 | Returns a boolean for whether the given type is a union.
 5 | 
 6 | @example
 7 | ```
 8 | import type {IsUnion} from 'type-fest';
 9 | 
10 | type A = IsUnion<string | number>;
11 | //=> true
12 | 
13 | type B = IsUnion<string>;
14 | //=> false
15 | ```
16 | */
17 | export type IsUnion<T> = InternalIsUnion<T>;
18 | 
19 | /**
20 | The actual implementation of `IsUnion`.
21 | */
22 | type InternalIsUnion<T, U = T> =
23 | (
24 | 	IsNever<T> extends true
25 | 		? false
26 | 		: T extends any
27 | 			? [U] extends [T]
28 | 				? false
29 | 				: true
30 | 			: never
31 | ) extends infer Result
32 | 	// In some cases `Result` will return `false | true` which is `boolean`,
33 | 	// that means `T` has at least two types and it's a union type,
34 | 	// so we will return `true` instead of `boolean`.
35 | 	? boolean extends Result ? true
36 | 		: Result
37 | 	: never; // Should never happen
38 | 


--------------------------------------------------------------------------------
/source/is-unknown.d.ts:
--------------------------------------------------------------------------------
 1 | import type {IsNull} from './is-null.d.ts';
 2 | 
 3 | /**
 4 | Returns a boolean for whether the given type is `unknown`.
 5 | 
 6 | @link https://github.com/dsherret/conditional-type-checks/pull/16
 7 | 
 8 | Useful in type utilities, such as when dealing with unknown data from API calls.
 9 | 
10 | @example
11 | ```
12 | import type {IsUnknown} from 'type-fest';
13 | 
14 | // https://github.com/pajecawav/tiny-global-store/blob/master/src/index.ts
15 | type Action<TState, TPayload = void> =
16 | 	IsUnknown<TPayload> extends true
17 | 		? (state: TState) => TState,
18 | 		: (state: TState, payload: TPayload) => TState;
19 | 
20 | class Store<TState> {
21 | 	constructor(private state: TState) {}
22 | 
23 | 	execute<TPayload = void>(action: Action<TState, TPayload>, payload?: TPayload): TState {
24 | 		this.state = action(this.state, payload);
25 | 		return this.state;
26 | 	}
27 | 
28 | 	// ... other methods
29 | }
30 | 
31 | const store = new Store({value: 1});
32 | declare const someExternalData: unknown;
33 | 
34 | store.execute(state => ({value: state.value + 1}));
35 | //=> `TPayload` is `void`
36 | 
37 | store.execute((state, payload) => ({value: state.value + payload}), 5);
38 | //=> `TPayload` is `5`
39 | 
40 | store.execute((state, payload) => ({value: state.value + payload}), someExternalData);
41 | //=> Errors: `action` is `(state: TState) => TState`
42 | ```
43 | 
44 | @category Utilities
45 | */
46 | export type IsUnknown<T> = (
47 | 	unknown extends T // `T` can be `unknown` or `any`
48 | 		? IsNull<T> extends false // `any` can be `null`, but `unknown` can't be
49 | 			? true
50 | 			: false
51 | 		: false
52 | );
53 | 


--------------------------------------------------------------------------------
/source/is-uppercase.d.ts:
--------------------------------------------------------------------------------
 1 | import type {AllExtend} from './all-extend.d.ts';
 2 | 
 3 | /**
 4 | Returns a boolean for whether the given string literal is uppercase.
 5 | 
 6 | @example
 7 | ```
 8 | import type {IsUppercase} from 'type-fest';
 9 | 
10 | IsUppercase<'ABC'>;
11 | //=> true
12 | 
13 | IsUppercase<'Abc'>;
14 | //=> false
15 | 
16 | IsUppercase<string>;
17 | //=> boolean
18 | ```
19 | */
20 | export type IsUppercase<S extends string> = AllExtend<_IsUppercase<S>, true>;
21 | 
22 | /**
23 | Loops through each part in the string and returns a boolean array indicating whether each part is uppercase.
24 | */
25 | type _IsUppercase<S extends string, Accumulator extends boolean[] = []> = S extends `${infer First}${infer Rest}`
26 | 	? _IsUppercase<Rest, [...Accumulator, IsUppercaseHelper<First>]>
27 | 	: [...Accumulator, IsUppercaseHelper<S>];
28 | 
29 | /**
30 | Returns a boolean for whether an individual part of the string is uppercase.
31 | */
32 | type IsUppercaseHelper<S extends string> = S extends Uppercase<string>
33 | 	? true
34 | 	: S extends Lowercase<string> | Uncapitalize<string> | `${string}${Lowercase<string>}${string}`
35 | 		? false
36 | 		: boolean;
37 | 


--------------------------------------------------------------------------------
/source/json-value.d.ts:
--------------------------------------------------------------------------------
 1 | /**
 2 | Matches a JSON object.
 3 | 
 4 | 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 { … }`.
 5 | 
 6 | @category JSON
 7 | */
 8 | export type JsonObject = {[Key in string]: JsonValue} & {[Key in string]?: JsonValue | undefined};
 9 | 
10 | /**
11 | Matches a JSON array.
12 | 
13 | @category JSON
14 | */
15 | export type JsonArray = JsonValue[] | readonly JsonValue[];
16 | 
17 | /**
18 | Matches any valid JSON primitive value.
19 | 
20 | @category JSON
21 | */
22 | export type JsonPrimitive = string | number | boolean | null;
23 | 
24 | /**
25 | Matches any valid JSON value.
26 | 
27 | @see `Jsonify` if you need to transform a type to one that is assignable to `JsonValue`.
28 | 
29 | @category JSON
30 | */
31 | export type JsonValue = JsonPrimitive | JsonObject | JsonArray;
32 | 


--------------------------------------------------------------------------------
/source/jsonifiable.d.ts:
--------------------------------------------------------------------------------
 1 | import type {JsonPrimitive} from './json-value.d.ts';
 2 | 
 3 | type JsonifiableObject = {[Key in string]?: Jsonifiable} | {toJSON: () => Jsonifiable};
 4 | type JsonifiableArray = readonly Jsonifiable[];
 5 | 
 6 | /**
 7 | Matches a value that can be losslessly converted to JSON.
 8 | 
 9 | Can be used to type values that you expect to pass to `JSON.stringify`.
10 | 
11 | `undefined` is allowed in object fields (for example, `{a?: number}`) as a special case even though `JSON.stringify({a: undefined})` is `{}` because it makes this class more widely useful and checking for undefined-but-present values is likely an anti-pattern.
12 | 
13 | @example
14 | ```
15 | import type {Jsonifiable} from 'type-fest';
16 | 
17 | // @ts-expect-error
18 | const error: Jsonifiable = {
19 |     map: new Map([['a', 1]]),
20 | };
21 | 
22 | JSON.stringify(error);
23 | //=> {"map": {}}
24 | 
25 | const good: Jsonifiable = {
26 |     number: 3,
27 |     date: new Date(),
28 |     missing: undefined,
29 | }
30 | 
31 | JSON.stringify(good);
32 | //=> {"number": 3, "date": "2022-10-17T22:22:35.920Z"}
33 | ```
34 | 
35 | @category JSON
36 | */
37 | export type Jsonifiable = JsonPrimitive | JsonifiableObject | JsonifiableArray;
38 | 


--------------------------------------------------------------------------------
/source/kebab-case.d.ts:
--------------------------------------------------------------------------------
 1 | import type {DefaultDelimiterCaseOptions, DelimiterCase} from './delimiter-case.d.ts';
 2 | import type {ApplyDefaultOptions} from './internal/index.d.ts';
 3 | import type {WordsOptions} from './words.d.ts';
 4 | 
 5 | /**
 6 | Convert a string literal to kebab-case.
 7 | 
 8 | This can be useful when, for example, converting a camel-cased object property to a kebab-cased CSS class name or a command-line flag.
 9 | 
10 | @example
11 | ```
12 | import type {KebabCase} from 'type-fest';
13 | 
14 | // Simple
15 | 
16 | const someVariable: KebabCase<'fooBar'> = 'foo-bar';
17 | const someVariableNoSplitOnNumbers: KebabCase<'p2pNetwork', {splitOnNumbers: false}> = 'p2p-network';
18 | 
19 | // Advanced
20 | 
21 | type KebabCasedProperties<T> = {
22 | 	[K in keyof T as KebabCase<K>]: T[K]
23 | };
24 | 
25 | interface CliOptions {
26 | 	dryRun: boolean;
27 | 	includeFile: string;
28 | 	foo: number;
29 | }
30 | 
31 | const rawCliOptions: KebabCasedProperties<CliOptions> = {
32 | 	'dry-run': true,
33 | 	'include-file': 'bar.js',
34 | 	foo: 123
35 | };
36 | ```
37 | 
38 | @category Change case
39 | @category Template literal
40 | */
41 | export type KebabCase<
42 | 	Value,
43 | 	Options extends WordsOptions = {},
44 | > = DelimiterCase<Value, '-', ApplyDefaultOptions<WordsOptions, DefaultDelimiterCaseOptions, Options>>;
45 | 


--------------------------------------------------------------------------------
/source/kebab-cased-properties-deep.d.ts:
--------------------------------------------------------------------------------
 1 | import type {DefaultDelimiterCaseOptions} from './delimiter-case.d.ts';
 2 | import type {DelimiterCasedPropertiesDeep} from './delimiter-cased-properties-deep.d.ts';
 3 | import type {ApplyDefaultOptions} from './internal/index.d.ts';
 4 | import type {WordsOptions} from './words.d.ts';
 5 | 
 6 | /**
 7 | Convert object properties to kebab case recursively.
 8 | 
 9 | This can be useful when, for example, converting some API types from a different style.
10 | 
11 | @see KebabCase
12 | @see KebabCasedProperties
13 | 
14 | @example
15 | ```
16 | import type [KebabCasedPropertiesDeep] from 'type-fest';
17 | 
18 | interface User {
19 | 	userId: number;
20 | 	userName: string;
21 | }
22 | 
23 | interface UserWithFriends {
24 | 	userInfo: User;
25 | 	userFriends: User[];
26 | }
27 | 
28 | const result: KebabCasedPropertiesDeep<UserWithFriends> = {
29 | 	'user-info': {
30 | 		'user-id': 1,
31 | 		'user-name': 'Tom',
32 | 	},
33 | 	'user-friends': [
34 | 		{
35 | 			'user-id': 2,
36 | 			'user-name': 'Jerry',
37 | 		},
38 | 		{
39 | 			'user-id': 3,
40 | 			'user-name': 'Spike',
41 | 		},
42 | 	],
43 | };
44 | 
45 | const splitOnNumbers: KebabCasedPropertiesDeep<{line1: { line2: [{ line3: string }] }}, {splitOnNumbers: true}> = {
46 | 	'line-1': {
47 | 		'line-2': [
48 | 			{
49 | 				'line-3': 'string',
50 | 			},
51 | 		],
52 | 	},
53 | };
54 | ```
55 | 
56 | @category Change case
57 | @category Template literal
58 | @category Object
59 | */
60 | export type KebabCasedPropertiesDeep<
61 | 	Value,
62 | 	Options extends WordsOptions = {},
63 | > = DelimiterCasedPropertiesDeep<Value, '-', ApplyDefaultOptions<WordsOptions, DefaultDelimiterCaseOptions, Options>>;
64 | 


--------------------------------------------------------------------------------
/source/kebab-cased-properties.d.ts:
--------------------------------------------------------------------------------
 1 | import type {DefaultDelimiterCaseOptions} from './delimiter-case.d.ts';
 2 | import type {DelimiterCasedProperties} from './delimiter-cased-properties.d.ts';
 3 | import type {ApplyDefaultOptions} from './internal/index.d.ts';
 4 | import type {WordsOptions} from './words.d.ts';
 5 | 
 6 | /**
 7 | Convert object properties to kebab case but not recursively.
 8 | 
 9 | This can be useful when, for example, converting some API types from a different style.
10 | 
11 | @see KebabCase
12 | @see KebabCasedPropertiesDeep
13 | 
14 | @example
15 | ```
16 | import type {KebabCasedProperties} from 'type-fest';
17 | 
18 | interface User {
19 | 	userId: number;
20 | 	userName: string;
21 | }
22 | 
23 | const result: KebabCasedProperties<User> = {
24 | 	'user-id': 1,
25 | 	'user-name': 'Tom',
26 | };
27 | 
28 | const splitOnNumbers: KebabCasedProperties<{line1: string}, {splitOnNumbers: true}> = {
29 | 	'line-1': 'string',
30 | };
31 | ```
32 | 
33 | @category Change case
34 | @category Template literal
35 | @category Object
36 | */
37 | export type KebabCasedProperties<
38 | 	Value,
39 | 	Options extends WordsOptions = {},
40 | > = DelimiterCasedProperties<Value, '-', ApplyDefaultOptions<WordsOptions, DefaultDelimiterCaseOptions, Options>>;
41 | 


--------------------------------------------------------------------------------
/source/key-as-string.d.ts:
--------------------------------------------------------------------------------
 1 | /**
 2 | Get keys of the given type as strings.
 3 | 
 4 | Number keys are converted to strings.
 5 | 
 6 | Use-cases:
 7 | - Get string keys from a type which may have number keys.
 8 | - Makes it possible to index using strings retrieved from template types.
 9 | 
10 | @example
11 | ```
12 | import type {KeyAsString} from 'type-fest';
13 | 
14 | type Foo = {
15 | 	1: number;
16 | 	stringKey: string;
17 | };
18 | 
19 | type StringKeysOfFoo = KeyAsString<Foo>;
20 | //=> '1' | 'stringKey'
21 | ```
22 | 
23 | @category Object
24 | */
25 | export type KeyAsString<BaseType> = `${Extract<keyof BaseType, string | number>}`;
26 | 


--------------------------------------------------------------------------------
/source/keys-of-union.d.ts:
--------------------------------------------------------------------------------
 1 | import type {UnionToIntersection} from './union-to-intersection.d.ts';
 2 | 
 3 | /**
 4 | Create a union of all keys from a given type, even those exclusive to specific union members.
 5 | 
 6 | Unlike the native `keyof` keyword, which returns keys present in **all** union members, this type returns keys from **any** member.
 7 | 
 8 | @link https://stackoverflow.com/a/49402091
 9 | 
10 | @example
11 | ```
12 | import type {KeysOfUnion} from 'type-fest';
13 | 
14 | type A = {
15 | 	common: string;
16 | 	a: number;
17 | };
18 | 
19 | type B = {
20 | 	common: string;
21 | 	b: string;
22 | };
23 | 
24 | type C = {
25 | 	common: string;
26 | 	c: boolean;
27 | };
28 | 
29 | type Union = A | B | C;
30 | 
31 | type CommonKeys = keyof Union;
32 | //=> 'common'
33 | 
34 | type AllKeys = KeysOfUnion<Union>;
35 | //=> 'common' | 'a' | 'b' | 'c'
36 | ```
37 | 
38 | @category Object
39 | */
40 | export type KeysOfUnion<ObjectType> =
41 |   // Hack to fix https://github.com/sindresorhus/type-fest/issues/1008
42 |   keyof UnionToIntersection<ObjectType extends unknown ? Record<keyof ObjectType, never> : never>;
43 | 


--------------------------------------------------------------------------------
/source/last-array-element.d.ts:
--------------------------------------------------------------------------------
 1 | /**
 2 | Extracts the type of the last element of an array.
 3 | 
 4 | Use-case: Defining the return type of functions that extract the last element of an array, for example [`lodash.last`](https://lodash.com/docs/4.17.15#last).
 5 | 
 6 | @example
 7 | ```
 8 | import type {LastArrayElement} from 'type-fest';
 9 | 
10 | declare function lastOf<V extends readonly any[]>(array: V): LastArrayElement<V>;
11 | 
12 | const array = ['foo', 2];
13 | 
14 | typeof lastOf(array);
15 | //=> number
16 | 
17 | const array = ['foo', 2] as const;
18 | 
19 | typeof lastOf(array);
20 | //=> 2
21 | ```
22 | 
23 | @category Array
24 | @category Template literal
25 | */
26 | export type LastArrayElement<Elements extends readonly unknown[], ElementBeforeTailingSpreadElement = never> =
27 | 	// If the last element of an array is a spread element, the `LastArrayElement` result should be `'the type of the element before the spread element' | 'the type of the spread element'`.
28 | 	Elements extends readonly []
29 | 		? ElementBeforeTailingSpreadElement
30 | 		: Elements extends readonly [...infer U, infer V]
31 | 			? V
32 | 			: Elements extends readonly [infer U, ...infer V]
33 | 				// If we return `V[number] | U` directly, it would be wrong for `[[string, boolean, object, ...number[]]`.
34 | 				// So we need to recurse type `V` and carry over the type of the element before the spread element.
35 | 				? LastArrayElement<V, U>
36 | 				: Elements extends ReadonlyArray<infer U>
37 | 					? U | ElementBeforeTailingSpreadElement
38 | 					: never;
39 | 


--------------------------------------------------------------------------------
/source/less-than-or-equal.d.ts:
--------------------------------------------------------------------------------
 1 | import type {GreaterThan} from './greater-than.d.ts';
 2 | 
 3 | /**
 4 |  Returns a boolean for whether a given number is less than or equal to another number.
 5 | 
 6 | @example
 7 | ```
 8 | import type {LessThanOrEqual} from 'type-fest';
 9 | 
10 | LessThanOrEqual<1, -5>;
11 | //=> false
12 | 
13 | LessThanOrEqual<1, 1>;
14 | //=> true
15 | 
16 | LessThanOrEqual<1, 5>;
17 | //=> true
18 | ```
19 | */
20 | export type LessThanOrEqual<A extends number, B extends number> = number extends A | B
21 | 	? never
22 | 	: GreaterThan<A, B> extends true ? false : true;
23 | 


--------------------------------------------------------------------------------
/source/less-than.d.ts:
--------------------------------------------------------------------------------
 1 | import type {GreaterThanOrEqual} from './greater-than-or-equal.d.ts';
 2 | 
 3 | /**
 4 | Returns a boolean for whether a given number is less than another number.
 5 | 
 6 | @example
 7 | ```
 8 | import type {LessThan} from 'type-fest';
 9 | 
10 | LessThan<1, -5>;
11 | //=> false
12 | 
13 | LessThan<1, 1>;
14 | //=> false
15 | 
16 | LessThan<1, 5>;
17 | //=> true
18 | ```
19 | */
20 | export type LessThan<A extends number, B extends number> = number extends A | B
21 | 	? never
22 | 	: GreaterThanOrEqual<A, B> extends infer Result
23 | 		? Result extends true
24 | 			? false
25 | 			: true
26 | 		: never; // Should never happen
27 | 


--------------------------------------------------------------------------------
/source/literal-to-primitive-deep.d.ts:
--------------------------------------------------------------------------------
 1 | import type {LiteralToPrimitive} from './literal-to-primitive.d.ts';
 2 | import type {OmitIndexSignature} from './omit-index-signature.d.ts';
 3 | 
 4 | /**
 5 | Like `LiteralToPrimitive` except it converts literal types inside an object or array deeply.
 6 | 
 7 | For example, given a constant object, it returns a new object type with the same keys but with all the values converted to primitives.
 8 | 
 9 | @see LiteralToPrimitive
10 | 
11 | Use-case: Deal with data that is imported from a JSON file.
12 | 
13 | @example
14 | ```
15 | import type {LiteralToPrimitiveDeep, TsConfigJson} from 'type-fest';
16 | import tsconfig from 'path/to/tsconfig.json';
17 | 
18 | function doSomethingWithTSConfig(config: LiteralToPrimitiveDeep<TsConfigJson>) { ... }
19 | 
20 | // No casting is needed to pass the type check
21 | doSomethingWithTSConfig(tsconfig);
22 | 
23 | // If LiteralToPrimitiveDeep is not used, you need to cast the imported data like this:
24 | doSomethingWithTSConfig(tsconfig as TsConfigJson);
25 | ```
26 | 
27 | @category Type
28 | @category Object
29 | */
30 | export type LiteralToPrimitiveDeep<T> = T extends object
31 | 	? T extends Array<infer U>
32 | 		? Array<LiteralToPrimitiveDeep<U>>
33 | 		: {
34 | 			[K in keyof OmitIndexSignature<T>]: LiteralToPrimitiveDeep<T[K]>;
35 | 		}
36 | 	: LiteralToPrimitive<T>;
37 | 


--------------------------------------------------------------------------------
/source/literal-to-primitive.d.ts:
--------------------------------------------------------------------------------
 1 | /**
 2 | Given a [literal type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#literal-types) return the {@link Primitive | primitive type} it belongs to, or `never` if it's not a primitive.
 3 | 
 4 | Use-case: Working with generic types that may be literal types.
 5 | 
 6 | @example
 7 | ```
 8 | import type {LiteralToPrimitive} from 'type-fest';
 9 | 
10 | // No overloads needed to get the correct return type
11 | function plus<T extends number | bigint | string>(x: T, y: T): LiteralToPrimitive<T> {
12 | 	return x + (y as any);
13 | }
14 | 
15 | plus('a', 'b'); // string
16 | plus(1, 2); // number
17 | plus(1n, 2n); // bigint
18 | ```
19 | 
20 | @category Type
21 | */
22 | export type LiteralToPrimitive<T> = T extends number
23 | 	? number
24 | 	: T extends bigint
25 | 		? bigint
26 | 		: T extends string
27 | 			? string
28 | 			: T extends boolean
29 | 				? boolean
30 | 				: T extends symbol
31 | 					? symbol
32 | 					: T extends null
33 | 						? null
34 | 						: T extends undefined
35 | 							? undefined
36 | 							: never;
37 | 


--------------------------------------------------------------------------------
/source/literal-union.d.ts:
--------------------------------------------------------------------------------
 1 | import type {Primitive} from './primitive.d.ts';
 2 | 
 3 | export type LiteralStringUnion<T> = LiteralUnion<T, string>;
 4 | 
 5 | /**
 6 | 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.
 7 | 
 8 | 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.
 9 | 
10 | 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.
11 | 
12 | @example
13 | ```
14 | import type {LiteralUnion} from 'type-fest';
15 | 
16 | // Before
17 | 
18 | type Pet = 'dog' | 'cat' | string;
19 | 
20 | const pet: Pet = '';
21 | // Start typing in your TypeScript-enabled IDE.
22 | // You **will not** get auto-completion for `dog` and `cat` literals.
23 | 
24 | // After
25 | 
26 | type Pet2 = LiteralUnion<'dog' | 'cat', string>;
27 | 
28 | const pet: Pet2 = '';
29 | // You **will** get auto-completion for `dog` and `cat` literals.
30 | ```
31 | 
32 | @category Type
33 | */
34 | export type LiteralUnion<
35 | 	LiteralType,
36 | 	BaseType extends Primitive,
37 | > = LiteralType | (BaseType & Record<never, never>);
38 | 


--------------------------------------------------------------------------------
/source/merge-exclusive.d.ts:
--------------------------------------------------------------------------------
 1 | // Helper type. Not useful on its own.
 2 | type Without<FirstType, SecondType> = {[KeyType in Exclude<keyof FirstType, keyof SecondType>]?: 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<FirstType, SecondType>` 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 type {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<ExclusiveVariation1, ExclusiveVariation2>;
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 | @category Object
36 | */
37 | export type MergeExclusive<FirstType, SecondType> =
38 | 	(FirstType | SecondType) extends object ?
39 | 		(Without<FirstType, SecondType> & SecondType) | (Without<SecondType, FirstType> & FirstType) :
40 | 		FirstType | SecondType;
41 | 
42 | 


--------------------------------------------------------------------------------
/source/merge.d.ts:
--------------------------------------------------------------------------------
 1 | import type {OmitIndexSignature} from './omit-index-signature.d.ts';
 2 | import type {PickIndexSignature} from './pick-index-signature.d.ts';
 3 | import type {Simplify} from './simplify.d.ts';
 4 | 
 5 | // Merges two objects without worrying about index signatures.
 6 | type SimpleMerge<Destination, Source> = {
 7 | 	[Key in keyof Destination as Key extends keyof Source ? never : Key]: Destination[Key];
 8 | } & Source;
 9 | 
10 | /**
11 | Merge two types into a new type. Keys of the second type overrides keys of the first type.
12 | 
13 | @example
14 | ```
15 | import type {Merge} from 'type-fest';
16 | 
17 | interface Foo {
18 | 	[x: string]: unknown;
19 | 	[x: number]: unknown;
20 | 	foo: string;
21 | 	bar: symbol;
22 | }
23 | 
24 | type Bar = {
25 | 	[x: number]: number;
26 | 	[x: symbol]: unknown;
27 | 	bar: Date;
28 | 	baz: boolean;
29 | };
30 | 
31 | export type FooBar = Merge<Foo, Bar>;
32 | // => {
33 | // 	[x: string]: unknown;
34 | // 	[x: number]: number;
35 | // 	[x: symbol]: unknown;
36 | // 	foo: string;
37 | // 	bar: Date;
38 | // 	baz: boolean;
39 | // }
40 | ```
41 | 
42 | @category Object
43 | */
44 | export type Merge<Destination, Source> =
45 | Simplify<
46 | 	SimpleMerge<PickIndexSignature<Destination>, PickIndexSignature<Source>>
47 | 	& SimpleMerge<OmitIndexSignature<Destination>, OmitIndexSignature<Source>>
48 | >;
49 | 


--------------------------------------------------------------------------------
/source/multidimensional-array.d.ts:
--------------------------------------------------------------------------------
 1 | import type {Subtract} from './subtract.d.ts';
 2 | import type {IsEqual} from './is-equal.d.ts';
 3 | 
 4 | type Recursive<T> = Array<Recursive<T>>;
 5 | 
 6 | /**
 7 | Creates a type that represents a multidimensional array of the given type and dimension.
 8 | 
 9 | Use-cases:
10 | - Return a n-dimensional array from functions.
11 | - Declare a n-dimensional array by defining its dimensions rather than declaring `[]` repetitively.
12 | - Infer the dimensions of a n-dimensional array automatically from function arguments.
13 | - Avoid the need to know in advance the dimensions of a n-dimensional array allowing them to be dynamic.
14 | 
15 | @example
16 | ```
17 | import type {MultidimensionalArray} from 'type-fest';
18 | 
19 | function emptyMatrix<T extends number>(dimensions: T): MultidimensionalArray<unknown, T> {
20 | 	const matrix: unknown[] = [];
21 | 
22 | 	let subMatrix = matrix;
23 | 	for (let dimension = 1; dimension < dimensions; ++dimension) {
24 | 		console.log(`Initializing dimension #${dimension}`);
25 | 
26 | 		subMatrix[0] = [];
27 | 		subMatrix = subMatrix[0] as unknown[];
28 | 	}
29 | 
30 | 	return matrix as MultidimensionalArray<unknown, T>;
31 | }
32 | 
33 | const matrix = emptyMatrix(3);
34 | 
35 | matrix[0][0][0] = 42;
36 | ```
37 | 
38 | @category Array
39 | */
40 | export type MultidimensionalArray<Element, Dimensions extends number> = number extends Dimensions
41 | 	? Recursive<Element>
42 | 	: IsEqual<Dimensions, 0> extends true
43 | 		? Element
44 | 		: Array<MultidimensionalArray<Element, Subtract<Dimensions, 1>>>;
45 | 


--------------------------------------------------------------------------------
/source/multidimensional-readonly-array.d.ts:
--------------------------------------------------------------------------------
 1 | import type {Subtract} from './subtract.d.ts';
 2 | import type {IsEqual} from './is-equal.d.ts';
 3 | 
 4 | type Recursive<T> = ReadonlyArray<Recursive<T>>;
 5 | 
 6 | /**
 7 | Creates a type that represents a multidimensional readonly array that of the given type and dimension.
 8 | 
 9 | Use-cases:
10 | - Return a n-dimensional array from functions.
11 | - Declare a n-dimensional array by defining its dimensions rather than declaring `[]` repetitively.
12 | - Infer the dimensions of a n-dimensional array automatically from function arguments.
13 | - Avoid the need to know in advance the dimensions of a n-dimensional array allowing them to be dynamic.
14 | 
15 | @example
16 | ```
17 | import type {MultidimensionalReadonlyArray} from 'type-fest';
18 | 
19 | function emptyMatrix<T extends number>(dimensions: T): MultidimensionalReadonlyArray<unknown, T> {
20 | 	const matrix: unknown[] = [];
21 | 
22 | 	let subMatrix = matrix;
23 | 	for (let dimension = 1; dimension < dimensions; ++dimension) {
24 | 		console.log(`Initializing dimension #${dimension}`);
25 | 
26 | 		subMatrix[0] = [];
27 | 		if (dimension < dimensions - 1) {
28 | 			subMatrix = subMatrix[0] as unknown[];
29 | 		} else {
30 | 			subMatrix[0] = 42;
31 | 		}
32 | 	}
33 | 
34 | 	return matrix as MultidimensionalReadonlyArray<unknown, T>;
35 | }
36 | 
37 | const matrix = emptyMatrix(3);
38 | 
39 | const answer = matrix[0][0][0]; // 42
40 | ```
41 | 
42 | @category Array
43 | */
44 | export type MultidimensionalReadonlyArray<Element, Dimensions extends number> = number extends Dimensions
45 | 	? Recursive<Element>
46 | 	: IsEqual<Dimensions, 0> extends true
47 | 		? Element
48 | 		: ReadonlyArray<MultidimensionalReadonlyArray<Element, Subtract<Dimensions, 1>>>;
49 | 


--------------------------------------------------------------------------------
/source/non-empty-object.d.ts:
--------------------------------------------------------------------------------
 1 | import type {HasRequiredKeys} from './has-required-keys.d.ts';
 2 | import type {RequireAtLeastOne} from './require-at-least-one.d.ts';
 3 | 
 4 | /**
 5 | Represents an object with at least 1 non-optional key.
 6 | 
 7 | This is useful when you need an object where all keys are optional, but there must be at least 1 key.
 8 | 
 9 | @example
10 | ```
11 | import type {NonEmptyObject} from 'type-fest';
12 | 
13 | type User = {
14 | 	name: string;
15 | 	surname: string;
16 | 	id: number;
17 | };
18 | 
19 | type UpdateRequest<Entity extends object> = NonEmptyObject<Partial<Entity>>;
20 | 
21 | const update1: UpdateRequest<User> = {
22 | 	name: 'Alice',
23 | 	surname: 'Acme',
24 | };
25 | 
26 | // At least 1 key is required, therefore this will report a 2322 error:
27 | // Type '{}' is not assignable to type 'UpdateRequest<User>'
28 | const update2: UpdateRequest<User> = {};
29 | ```
30 | 
31 | @see Use `IsEmptyObject` to check whether an object is empty.
32 | 
33 | @category Object
34 | */
35 | export type NonEmptyObject<T extends object> = HasRequiredKeys<T> extends true ? T : RequireAtLeastOne<T, keyof T>;
36 | 


--------------------------------------------------------------------------------
/source/non-empty-string.d.ts:
--------------------------------------------------------------------------------
 1 | /**
 2 | Matches any non-empty string.
 3 | 
 4 | This is useful when you need a string that is not empty, for example, as a function parameter.
 5 | 
 6 | NOTE:
 7 | - This returns `never` not just when instantiated with an empty string, but also when an empty string is a subtype of the instantiated type, like `string` or `Uppercase<string>`.
 8 | 
 9 | @example
10 | ```
11 | import type {NonEmptyString} from 'type-fest';
12 | 
13 | declare function foo<T extends string>(string: NonEmptyString<T>): void;
14 | 
15 | foo('a');
16 | //=> OK
17 | 
18 | foo('');
19 | //=> Error: Argument of type '""' is not assignable to parameter of type 'never'.
20 | 
21 | declare const someString: string
22 | foo(someString);
23 | //=> Error: Argument of type 'string' is not assignable to parameter of type 'never'.
24 | ```
25 | 
26 | @category String
27 | */
28 | export type NonEmptyString<T extends string> = '' extends T ? never : T;
29 | 


--------------------------------------------------------------------------------
/source/non-empty-tuple.d.ts:
--------------------------------------------------------------------------------
 1 | /**
 2 | Matches any non-empty tuple.
 3 | 
 4 | @example
 5 | ```
 6 | import type {NonEmptyTuple} from 'type-fest';
 7 | 
 8 | const sum = (...numbers: NonEmptyTuple<number>) => numbers.reduce((total, value) => total + value, 0);
 9 | 
10 | sum(1, 2, 3);
11 | //=> 6
12 | 
13 | sum();
14 | //=> Error: Expected at least 1 arguments, but got 0.
15 | ```
16 | 
17 | @see {@link RequireAtLeastOne} for objects
18 | 
19 | @category Array
20 | */
21 | export type NonEmptyTuple<T = unknown> = readonly [T, ...T[]];
22 | 


--------------------------------------------------------------------------------
/source/opaque.d.ts:
--------------------------------------------------------------------------------
1 | export type * from './tagged.d.ts';
2 | 


--------------------------------------------------------------------------------
/source/optional-keys-of.d.ts:
--------------------------------------------------------------------------------
 1 | /**
 2 | Extract all optional keys from the given type.
 3 | 
 4 | This is useful when you want to create a new type that contains different type values for the optional keys only.
 5 | 
 6 | @example
 7 | ```
 8 | import type {OptionalKeysOf, Except} from 'type-fest';
 9 | 
10 | interface User {
11 | 	name: string;
12 | 	surname: string;
13 | 
14 | 	luckyNumber?: number;
15 | }
16 | 
17 | const REMOVE_FIELD = Symbol('remove field symbol');
18 | type UpdateOperation<Entity extends object> = Except<Partial<Entity>, OptionalKeysOf<Entity>> & {
19 | 	[Key in OptionalKeysOf<Entity>]?: Entity[Key] | typeof REMOVE_FIELD;
20 | };
21 | 
22 | const update1: UpdateOperation<User> = {
23 | 	name: 'Alice'
24 | };
25 | 
26 | const update2: UpdateOperation<User> = {
27 | 	name: 'Bob',
28 | 	luckyNumber: REMOVE_FIELD
29 | };
30 | ```
31 | 
32 | @category Utilities
33 | */
34 | export type OptionalKeysOf<BaseType extends object> =
35 | 	BaseType extends unknown // For distributing `BaseType`
36 | 		? (keyof {
37 | 			[Key in keyof BaseType as BaseType extends Record<Key, BaseType[Key]> ? never : Key]: never
38 | 		}) & (keyof BaseType) // Intersect with `keyof BaseType` to ensure result of `OptionalKeysOf<BaseType>` is always assignable to `keyof BaseType`
39 | 		: never; // Should never happen
40 | 


--------------------------------------------------------------------------------
/source/override-properties.d.ts:
--------------------------------------------------------------------------------
 1 | import type {Merge} from './merge.d.ts';
 2 | 
 3 | /**
 4 | Override existing properties of the given type. Similar to `Merge`, but enforces that the original type has the properties you want to override.
 5 | 
 6 | This is useful when you want to override existing properties with a different type and make sure that these properties really exist in the original.
 7 | 
 8 | @example
 9 | ```
10 | type Foo = {
11 | 	a: string
12 | 	b: string
13 | }
14 | type Bar = OverrideProperties<Foo, {b: number}>
15 | //=> {a: string, b: number}
16 | 
17 | type Baz = OverrideProperties<Foo, {c: number}>
18 | // Error, type '{ c: number; }' does not satisfy the constraint '{ c: never; }'
19 | 
20 | type Fizz = OverrideProperties<Foo, {b: number; c: number}>
21 | // Error, type '{ b: number; c: number; }' does not satisfy the constraint '{ b: number; c: never; }'
22 | ```
23 | 
24 | @category Object
25 | */
26 | export type OverrideProperties<
27 | 	TOriginal,
28 | 	// This first bit where we use `Partial` is to enable autocomplete
29 | 	// and the second bit with the mapped type is what enforces that we don't try
30 | 	// to override properties that doesn't exist in the original type.
31 | 	TOverride extends Partial<Record<keyof TOriginal, unknown>> & {
32 | 		[Key in keyof TOverride]: Key extends keyof TOriginal
33 | 			? TOverride[Key]
34 | 			: never;
35 | 	},
36 | > = Merge<TOriginal, TOverride>;
37 | 


--------------------------------------------------------------------------------
/source/pascal-case.d.ts:
--------------------------------------------------------------------------------
 1 | import type {CamelCase, CamelCaseOptions, DefaultCamelCaseOptions} from './camel-case.d.ts';
 2 | import type {ApplyDefaultOptions} from './internal/index.d.ts';
 3 | 
 4 | /**
 5 | Converts a string literal to pascal-case.
 6 | 
 7 | @example
 8 | ```
 9 | import type {PascalCase} from 'type-fest';
10 | 
11 | // Simple
12 | 
13 | const someVariable: PascalCase<'foo-bar'> = 'FooBar';
14 | const preserveConsecutiveUppercase: PascalCase<'foo-BAR-baz', {preserveConsecutiveUppercase: true}> = 'FooBARBaz';
15 | 
16 | // Advanced
17 | 
18 | type PascalCasedProperties<T> = {
19 | 	[K in keyof T as PascalCase<K>]: T[K]
20 | };
21 | 
22 | interface RawOptions {
23 | 	'dry-run': boolean;
24 | 	'full_family_name': string;
25 | 	foo: number;
26 | 	BAR: string;
27 | 	QUZ_QUX: number;
28 | 	'OTHER-FIELD': boolean;
29 | };
30 | 
31 | const dbResult: PascalCasedProperties<RawOptions> = {
32 | 	DryRun: true,
33 | 	FullFamilyName: 'bar.js',
34 | 	Foo: 123,
35 | 	Bar: 'foo',
36 | 	QuzQux: 6,
37 | 	OtherField: false,
38 | };
39 | ```
40 | 
41 | @category Change case
42 | @category Template literal
43 | */
44 | export type PascalCase<Value, Options extends CamelCaseOptions = {}> =
45 | 	_PascalCase<Value, ApplyDefaultOptions<CamelCaseOptions, DefaultCamelCaseOptions, Options>>;
46 | 
47 | type _PascalCase<Value, Options extends Required<CamelCaseOptions>> = CamelCase<Value, Options> extends string
48 | 	? Capitalize<CamelCase<Value, Options>>
49 | 	: CamelCase<Value, Options>;
50 | 


--------------------------------------------------------------------------------
/source/pascal-cased-properties.d.ts:
--------------------------------------------------------------------------------
 1 | import type {CamelCaseOptions, DefaultCamelCaseOptions} from './camel-case.d.ts';
 2 | import type {ApplyDefaultOptions} from './internal/index.d.ts';
 3 | import type {PascalCase} from './pascal-case.d.ts';
 4 | 
 5 | /**
 6 | Convert object properties to pascal case but not recursively.
 7 | 
 8 | This can be useful when, for example, converting some API types from a different style.
 9 | 
10 | @see PascalCase
11 | @see PascalCasedPropertiesDeep
12 | 
13 | @example
14 | ```
15 | import type {PascalCasedProperties} from 'type-fest';
16 | 
17 | interface User {
18 | 	userId: number;
19 | 	userName: string;
20 | }
21 | 
22 | const result: PascalCasedProperties<User> = {
23 | 	UserId: 1,
24 | 	UserName: 'Tom',
25 | };
26 | 
27 | const preserveConsecutiveUppercase: PascalCasedProperties<{fooBAR: string}, {preserveConsecutiveUppercase: true}> = {
28 | 	FooBAR: 'string',
29 | };
30 | ```
31 | 
32 | @category Change case
33 | @category Template literal
34 | @category Object
35 | */
36 | export type PascalCasedProperties<Value, Options extends CamelCaseOptions = {}> = Value extends Function
37 | 	? Value
38 | 	: Value extends Array<infer U>
39 | 		? Value
40 | 		: {[K in keyof Value as PascalCase<K, ApplyDefaultOptions<CamelCaseOptions, DefaultCamelCaseOptions, Options>>]: Value[K]};
41 | 


--------------------------------------------------------------------------------
/source/pick-index-signature.d.ts:
--------------------------------------------------------------------------------
 1 | /**
 2 | Pick only index signatures from the given object type, leaving out all explicitly defined properties.
 3 | 
 4 | This is the counterpart of `OmitIndexSignature`.
 5 | 
 6 | @example
 7 | ```
 8 | import type {PickIndexSignature} from 'type-fest';
 9 | 
10 | declare const symbolKey: unique symbol;
11 | 
12 | type Example = {
13 | 	// These index signatures will remain.
14 | 	[x: string]: unknown;
15 | 	[x: number]: unknown;
16 | 	[x: symbol]: unknown;
17 | 	[x: `head-${string}`]: string;
18 | 	[x: `${string}-tail`]: string;
19 | 	[x: `head-${string}-tail`]: string;
20 | 	[x: `${bigint}`]: string;
21 | 	[x: `embedded-${number}`]: string;
22 | 
23 | 	// These explicitly defined keys will be removed.
24 | 	['kebab-case-key']: string;
25 | 	[symbolKey]: string;
26 | 	foo: 'bar';
27 | 	qux?: 'baz';
28 | };
29 | 
30 | type ExampleIndexSignature = PickIndexSignature<Example>;
31 | // {
32 | // 	[x: string]: unknown;
33 | // 	[x: number]: unknown;
34 | // 	[x: symbol]: unknown;
35 | // 	[x: `head-${string}`]: string;
36 | // 	[x: `${string}-tail`]: string;
37 | // 	[x: `head-${string}-tail`]: string;
38 | // 	[x: `${bigint}`]: string;
39 | // 	[x: `embedded-${number}`]: string;
40 | // }
41 | ```
42 | 
43 | @see OmitIndexSignature
44 | @category Object
45 | */
46 | export type PickIndexSignature<ObjectType> = {
47 | 	[KeyType in keyof ObjectType as {} extends Record<KeyType, unknown>
48 | 		? KeyType
49 | 		: never]: ObjectType[KeyType];
50 | };
51 | 


--------------------------------------------------------------------------------
/source/primitive.d.ts:
--------------------------------------------------------------------------------
 1 | /**
 2 | Matches any [primitive value](https://developer.mozilla.org/en-US/docs/Glossary/Primitive).
 3 | 
 4 | @category Type
 5 | */
 6 | export type Primitive =
 7 | 	| null
 8 | 	| undefined
 9 | 	| string
10 | 	| number
11 | 	| boolean
12 | 	| symbol
13 | 	| bigint;
14 | 


--------------------------------------------------------------------------------
/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 type {Promisable} from 'type-fest';
13 | 
14 | async function logger(getLogEntry: () => Promisable<string>): Promise<void> {
15 | 	const entry = await getLogEntry();
16 | 	console.log(entry);
17 | }
18 | 
19 | logger(() => 'foo');
20 | logger(() => Promise.resolve('bar'));
21 | ```
22 | 
23 | @category Async
24 | */
25 | export type Promisable<T> = T | PromiseLike<T>;
26 | 


--------------------------------------------------------------------------------
/source/readonly-keys-of.d.ts:
--------------------------------------------------------------------------------
 1 | import type {WritableKeysOf} from './writable-keys-of.d.ts';
 2 | 
 3 | /**
 4 | Extract all readonly keys from the given type.
 5 | 
 6 | This is useful when you want to create a new type that contains readonly keys only.
 7 | 
 8 | @example
 9 | ```
10 | import type {ReadonlyKeysOf} from 'type-fest';
11 | 
12 | interface User {
13 | 	name: string;
14 | 	surname: string;
15 | 	readonly id: number;
16 | }
17 | 
18 | type UpdateResponse<Entity extends object> = Pick<Entity, ReadonlyKeysOf<Entity>>;
19 | 
20 | const update1: UpdateResponse<User> = {
21 |     id: 123,
22 | };
23 | ```
24 | 
25 | @category Utilities
26 | */
27 | export type ReadonlyKeysOf<T extends object> =
28 | 	T extends unknown // For distributing `T`
29 | 		? Exclude<keyof T, WritableKeysOf<T>>
30 | 		: never; // Should never happen
31 | 


--------------------------------------------------------------------------------
/source/readonly-tuple.d.ts:
--------------------------------------------------------------------------------
 1 | /**
 2 | Creates a read-only tuple of type `Element` and with the length of `Length`.
 3 | 
 4 | @private
 5 | @see `ReadonlyTuple` which is safer because it tests if `Length` is a specific finite number.
 6 | */
 7 | type BuildTupleHelper<Element, Length extends number, Rest extends Element[]> =
 8 | 	Rest['length'] extends Length ?
 9 | 		readonly [...Rest] : // Terminate with readonly array (aka tuple)
10 | 		BuildTupleHelper<Element, Length, [Element, ...Rest]>;
11 | 
12 | /**
13 | Create a type that represents a read-only tuple of the given type and length.
14 | 
15 | Use-cases:
16 | - Declaring fixed-length tuples with a large number of items.
17 | - 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.
18 | - Creating a tuple of coordinates with a static length, for example, length of 3 for a 3D vector.
19 | 
20 | @example
21 | ```
22 | import {ReadonlyTuple} from 'type-fest';
23 | 
24 | type FencingTeam = ReadonlyTuple<string, 3>;
25 | 
26 | const guestFencingTeam: FencingTeam = ['Josh', 'Michael', 'Robert'];
27 | 
28 | const homeFencingTeam: FencingTeam = ['George', 'John'];
29 | //=> error TS2322: Type string[] is not assignable to type 'FencingTeam'
30 | 
31 | guestFencingTeam.push('Sam');
32 | //=> error TS2339: Property 'push' does not exist on type 'FencingTeam'
33 | ```
34 | 
35 | @category Utilities
36 | */
37 | export type ReadonlyTuple<Element, Length extends number> =
38 | 	number extends Length
39 | 		// Because `Length extends number` and `number extends Length`, then `Length` is not a specific finite number.
40 | 		? readonly Element[] // It's not fixed length.
41 | 		: BuildTupleHelper<Element, Length, []>; // Otherwise it is a fixed length tuple.
42 | 


--------------------------------------------------------------------------------
/source/require-at-least-one.d.ts:
--------------------------------------------------------------------------------
 1 | import type {Except} from './except.d.ts';
 2 | import type {If} from './if.d.ts';
 3 | import type {IfNotAnyOrNever} from './internal/index.d.ts';
 4 | import type {IsAny} from './is-any.d.ts';
 5 | import type {IsNever} from './is-never.d.ts';
 6 | 
 7 | /**
 8 | Create a type that requires at least one of the given keys. The remaining keys are kept as is.
 9 | 
10 | @example
11 | ```
12 | import type {RequireAtLeastOne} from 'type-fest';
13 | 
14 | type Responder = {
15 | 	text?: () => string;
16 | 	json?: () => string;
17 | 	secure?: boolean;
18 | };
19 | 
20 | const responder: RequireAtLeastOne<Responder, 'text' | 'json'> = {
21 | 	json: () => '{"message": "ok"}',
22 | 	secure: true
23 | };
24 | ```
25 | 
26 | @category Object
27 | */
28 | export type RequireAtLeastOne<
29 | 	ObjectType,
30 | 	KeysType extends keyof ObjectType = keyof ObjectType,
31 | > =
32 | 	IfNotAnyOrNever<ObjectType,
33 | 		If<IsNever<KeysType>,
34 | 			never,
35 | 			_RequireAtLeastOne<ObjectType, If<IsAny<KeysType>, keyof ObjectType, KeysType>>
36 | 		>>;
37 | 
38 | type _RequireAtLeastOne<
39 | 	ObjectType,
40 | 	KeysType extends keyof ObjectType,
41 | > = {
42 | 	// For each `Key` in `KeysType` make a mapped type:
43 | 	[Key in KeysType]-?: Required<Pick<ObjectType, Key>> & // 1. Make `Key`'s type required
44 | 	// 2. Make all other keys in `KeysType` optional
45 | 		Partial<Pick<ObjectType, Exclude<KeysType, Key>>>;
46 | }[KeysType] &
47 | // 3. Add the remaining keys not in `KeysType`
48 | Except<ObjectType, KeysType>;
49 | 


--------------------------------------------------------------------------------
/source/require-one-or-none.d.ts:
--------------------------------------------------------------------------------
 1 | import type {RequireExactlyOne} from './require-exactly-one.d.ts';
 2 | import type {IfNotAnyOrNever, RequireNone} from './internal/index.d.ts';
 3 | import type {If} from './if.d.ts';
 4 | import type {IsAny} from './is-any.d.ts';
 5 | import type {IsNever} from './is-never.d.ts';
 6 | 
 7 | /**
 8 | Create a type that requires exactly one of the given keys and disallows more, or none of the given keys. The remaining keys are kept as is.
 9 | 
10 | @example
11 | ```
12 | import type {RequireOneOrNone} from 'type-fest';
13 | 
14 | type Responder = RequireOneOrNone<{
15 | 	text: () => string;
16 | 	json: () => string;
17 | 	secure: boolean;
18 | }, 'text' | 'json'>;
19 | 
20 | const responder1: Responder = {
21 | 	secure: true
22 | };
23 | 
24 | const responder2: Responder = {
25 | 	text: () => '{"message": "hi"}',
26 | 	secure: true
27 | };
28 | 
29 | const responder3: Responder = {
30 | 	json: () => '{"message": "ok"}',
31 | 	secure: true
32 | };
33 | ```
34 | 
35 | @category Object
36 | */
37 | export type RequireOneOrNone<ObjectType, KeysType extends keyof ObjectType = keyof ObjectType> =
38 | 	IfNotAnyOrNever<ObjectType,
39 | 		If<IsNever<KeysType>,
40 | 			ObjectType,
41 | 			_RequireOneOrNone<ObjectType, If<IsAny<KeysType>, keyof ObjectType, KeysType>>
42 | 		>>;
43 | 
44 | type _RequireOneOrNone<ObjectType, KeysType extends keyof ObjectType> = (
45 | 	| RequireExactlyOne<ObjectType, KeysType>
46 | 	| RequireNone<KeysType>
47 | ) & Omit<ObjectType, KeysType>; // Ignore unspecified keys.
48 | 


--------------------------------------------------------------------------------
/source/required-keys-of.d.ts:
--------------------------------------------------------------------------------
 1 | import type {OptionalKeysOf} from './optional-keys-of.d.ts';
 2 | 
 3 | /**
 4 | Extract all required keys from the given type.
 5 | 
 6 | This is useful when you want to create a new type that contains different type values for the required keys only or use the list of keys for validation purposes, etc...
 7 | 
 8 | @example
 9 | ```
10 | import type {RequiredKeysOf} from 'type-fest';
11 | 
12 | declare function createValidation<Entity extends object, Key extends RequiredKeysOf<Entity> = RequiredKeysOf<Entity>>(field: Key, validator: (value: Entity[Key]) => boolean): ValidatorFn;
13 | 
14 | interface User {
15 | 	name: string;
16 | 	surname: string;
17 | 
18 | 	luckyNumber?: number;
19 | }
20 | 
21 | const validator1 = createValidation<User>('name', value => value.length < 25);
22 | const validator2 = createValidation<User>('surname', value => value.length < 25);
23 | ```
24 | 
25 | @category Utilities
26 | */
27 | export type RequiredKeysOf<BaseType extends object> =
28 | 	BaseType extends unknown // For distributing `BaseType`
29 | 		? Exclude<keyof BaseType, OptionalKeysOf<BaseType>>
30 | 		: never; // Should never happen
31 | 


--------------------------------------------------------------------------------
/source/screaming-snake-case.d.ts:
--------------------------------------------------------------------------------
 1 | import type {DefaultDelimiterCaseOptions} from './delimiter-case.d.ts';
 2 | import type {ApplyDefaultOptions} from './internal/index.d.ts';
 3 | import type {SnakeCase} from './snake-case.d.ts';
 4 | import type {WordsOptions} from './words.d.ts';
 5 | 
 6 | /**
 7 | Convert a string literal to screaming-snake-case.
 8 | 
 9 | This can be useful when, for example, converting a camel-cased object property to a screaming-snake-cased SQL column name.
10 | 
11 | @example
12 | ```
13 | import type {ScreamingSnakeCase} from 'type-fest';
14 | 
15 | const someVariable: ScreamingSnakeCase<'fooBar'> = 'FOO_BAR';
16 | const someVariableNoSplitOnNumbers: ScreamingSnakeCase<'p2pNetwork', {splitOnNumbers: false}> = 'P2P_NETWORK';
17 | 
18 | ```
19 | 
20 | @category Change case
21 | @category Template literal
22 |  */
23 | export type ScreamingSnakeCase<
24 | 	Value,
25 | 	Options extends WordsOptions = {},
26 | > = Value extends string
27 | 	? Uppercase<SnakeCase<Value, ApplyDefaultOptions<WordsOptions, DefaultDelimiterCaseOptions, Options>>>
28 | 	: Value;
29 | 


--------------------------------------------------------------------------------
/source/set-non-nullable.d.ts:
--------------------------------------------------------------------------------
 1 | /**
 2 | Create a type that makes the given keys non-nullable, where the remaining keys are kept as is.
 3 | 
 4 | If no keys are given, all keys will be made non-nullable.
 5 | 
 6 | Use-case: You want to define a single model where the only thing that changes is whether or not some or all of the keys are non-nullable.
 7 | 
 8 | @example
 9 | ```
10 | import type {SetNonNullable} from 'type-fest';
11 | 
12 | type Foo = {
13 | 	a: number | null;
14 | 	b: string | undefined;
15 | 	c?: boolean | null;
16 | }
17 | 
18 | type SomeNonNullable = SetNonNullable<Foo, 'b' | 'c'>;
19 | // type SomeNonNullable = {
20 | // 	a: number | null;
21 | // 	b: string; // Can no longer be undefined.
22 | // 	c?: boolean; // Can no longer be null, but is still optional.
23 | // }
24 | 
25 | type AllNonNullable = SetNonNullable<Foo>;
26 | // type AllNonNullable = {
27 | // 	a: number; // Can no longer be null.
28 | // 	b: string; // Can no longer be undefined.
29 | // 	c?: boolean; // Can no longer be null, but is still optional.
30 | // }
31 | ```
32 | 
33 | @category Object
34 | */
35 | export type SetNonNullable<BaseType, Keys extends keyof BaseType = keyof BaseType> = {
36 | 	[Key in keyof BaseType]: Key extends Keys
37 | 		? NonNullable<BaseType[Key]>
38 | 		: BaseType[Key];
39 | };
40 | 


--------------------------------------------------------------------------------
/source/set-optional.d.ts:
--------------------------------------------------------------------------------
 1 | import type {Except} from './except.d.ts';
 2 | import type {HomomorphicPick} from './internal/index.d.ts';
 3 | import type {Simplify} from './simplify.d.ts';
 4 | 
 5 | /**
 6 | Create a type that makes the given keys optional. The remaining keys are kept as is. The sister of the `SetRequired` type.
 7 | 
 8 | 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.
 9 | 
10 | @example
11 | ```
12 | import type {SetOptional} from 'type-fest';
13 | 
14 | type Foo = {
15 | 	a: number;
16 | 	b?: string;
17 | 	c: boolean;
18 | }
19 | 
20 | type SomeOptional = SetOptional<Foo, 'b' | 'c'>;
21 | // type SomeOptional = {
22 | // 	a: number;
23 | // 	b?: string; // Was already optional and still is.
24 | // 	c?: boolean; // Is now optional.
25 | // }
26 | ```
27 | 
28 | @category Object
29 | */
30 | export type SetOptional<BaseType, Keys extends keyof BaseType> =
31 | 	(BaseType extends (...arguments_: never) => any
32 | 		? (...arguments_: Parameters<BaseType>) => ReturnType<BaseType>
33 | 		: unknown)
34 | 	& _SetOptional<BaseType, Keys>;
35 | 
36 | type _SetOptional<BaseType, Keys extends keyof BaseType> =
37 | 	BaseType extends unknown // To distribute `BaseType` when it's a union type.
38 | 		? Simplify<
39 | 		// Pick just the keys that are readonly from the base type.
40 | 			Except<BaseType, Keys> &
41 | 		// Pick the keys that should be mutable from the base type and make them mutable.
42 | 			Partial<HomomorphicPick<BaseType, Keys>>
43 | 		>
44 | 		: never;
45 | 


--------------------------------------------------------------------------------
/source/set-readonly.d.ts:
--------------------------------------------------------------------------------
 1 | import type {Except} from './except.d.ts';
 2 | import type {HomomorphicPick} from './internal/index.d.ts';
 3 | import type {Simplify} from './simplify.d.ts';
 4 | 
 5 | /**
 6 | Create a type that makes the given keys readonly. The remaining keys are kept as is.
 7 | 
 8 | Use-case: You want to define a single model where the only thing that changes is whether or not some of the keys are readonly.
 9 | 
10 | @example
11 | ```
12 | import type {SetReadonly} from 'type-fest';
13 | 
14 | type Foo = {
15 | 	a: number;
16 | 	readonly b: string;
17 | 	c: boolean;
18 | }
19 | 
20 | type SomeReadonly = SetReadonly<Foo, 'b' | 'c'>;
21 | // type SomeReadonly = {
22 | // 	a: number;
23 | // 	readonly b: string; // Was already readonly and still is.
24 | // 	readonly c: boolean; // Is now readonly.
25 | // }
26 | ```
27 | 
28 | @category Object
29 | */
30 | export type SetReadonly<BaseType, Keys extends keyof BaseType> =
31 | 	(BaseType extends (...arguments_: never) => any
32 | 		? (...arguments_: Parameters<BaseType>) => ReturnType<BaseType>
33 | 		: unknown)
34 | 	& _SetReadonly<BaseType, Keys>;
35 | 
36 | export type _SetReadonly<BaseType, Keys extends keyof BaseType> =
37 | 	BaseType extends unknown // To distribute `BaseType` when it's a union type.
38 | 		? Simplify<
39 | 			Except<BaseType, Keys> &
40 | 			Readonly<HomomorphicPick<BaseType, Keys>>
41 | 		>
42 | 		: never;
43 | 


--------------------------------------------------------------------------------
/source/set-return-type.d.ts:
--------------------------------------------------------------------------------
 1 | import type {IsUnknown} from './is-unknown.d.ts';
 2 | 
 3 | /**
 4 | Create a function type with a return type of your choice and the same parameters as the given function type.
 5 | 
 6 | Use-case: You want to define a wrapped function that returns something different while receiving the same parameters. For example, you might want to wrap a function that can throw an error into one that will return `undefined` instead.
 7 | 
 8 | @example
 9 | ```
10 | import type {SetReturnType} from 'type-fest';
11 | 
12 | type MyFunctionThatCanThrow = (foo: SomeType, bar: unknown) => SomeOtherType;
13 | 
14 | type MyWrappedFunction = SetReturnType<MyFunctionThatCanThrow, SomeOtherType | undefined>;
15 | //=> type MyWrappedFunction = (foo: SomeType, bar: unknown) => SomeOtherType | undefined;
16 | ```
17 | 
18 | @category Function
19 | */
20 | export type SetReturnType<Function_ extends (...arguments_: any[]) => any, TypeToReturn> =
21 | 	// Just using `Parameters<Fn>` isn't ideal because it doesn't handle the `this` fake parameter.
22 | 	Function_ extends (this: infer ThisArgument, ...arguments_: infer Arguments) => any ? (
23 | 		// If a function did not specify the `this` fake parameter, it will be inferred to `unknown`.
24 | 		// We want to detect this situation just to display a friendlier type upon hovering on an IntelliSense-powered IDE.
25 | 		IsUnknown<ThisArgument> extends true ? (...arguments_: Arguments) => TypeToReturn : (this: ThisArgument, ...arguments_: Arguments) => TypeToReturn
26 | 	) : (
27 | 		// This part should be unreachable, but we make it meaningful just in case…
28 | 		(...arguments_: Parameters<Function_>) => TypeToReturn
29 | 	);
30 | 


--------------------------------------------------------------------------------
/source/single-key-object.d.ts:
--------------------------------------------------------------------------------
 1 | import type {IsEmptyObject} from './empty-object.d.ts';
 2 | import type {If} from './if.d.ts';
 3 | import type {IsUnion} from './is-union.d.ts';
 4 | 
 5 | /**
 6 | Create a type that only accepts an object with a single key.
 7 | 
 8 | @example
 9 | ```
10 | import type {SingleKeyObject} from 'type-fest';
11 | 
12 | const someFunction = <T>(parameter: SingleKeyObject<T>) => {};
13 | 
14 | someFunction({
15 | 	value: true
16 | });
17 | 
18 | someFunction({
19 | 	value: true,
20 | 	otherKey: true
21 | });
22 | // Error: Argument of type '{value: boolean; otherKey: boolean}' is not assignable to parameter of type 'never'.ts(2345)
23 | ```
24 | 
25 | @category Object
26 | */
27 | export type SingleKeyObject<ObjectType> =
28 | 	IsUnion<keyof ObjectType> extends true
29 | 		? never
30 | 		: If<IsEmptyObject<ObjectType>, never, ObjectType>;
31 | 


--------------------------------------------------------------------------------
/source/snake-case.d.ts:
--------------------------------------------------------------------------------
 1 | import type {DefaultDelimiterCaseOptions, DelimiterCase} from './delimiter-case.d.ts';
 2 | import type {ApplyDefaultOptions} from './internal/index.d.ts';
 3 | import type {WordsOptions} from './words.d.ts';
 4 | 
 5 | /**
 6 | Convert a string literal to snake-case.
 7 | 
 8 | This can be useful when, for example, converting a camel-cased object property to a snake-cased SQL column name.
 9 | 
10 | @example
11 | ```
12 | import type {SnakeCase} from 'type-fest';
13 | 
14 | // Simple
15 | 
16 | const someVariable: SnakeCase<'fooBar'> = 'foo_bar';
17 | const noSplitOnNumbers: SnakeCase<'p2pNetwork'> = 'p2p_network';
18 | const splitOnNumbers: SnakeCase<'p2pNetwork', {splitOnNumbers: true}> = 'p_2_p_network';
19 | 
20 | // Advanced
21 | 
22 | type SnakeCasedProperties<T> = {
23 | 	[K in keyof T as SnakeCase<K>]: T[K]
24 | };
25 | 
26 | interface ModelProps {
27 | 	isHappy: boolean;
28 | 	fullFamilyName: string;
29 | 	foo: number;
30 | }
31 | 
32 | const dbResult: SnakeCasedProperties<ModelProps> = {
33 | 	'is_happy': true,
34 | 	'full_family_name': 'Carla Smith',
35 | 	foo: 123
36 | };
37 | ```
38 | 
39 | @category Change case
40 | @category Template literal
41 | */
42 | export type SnakeCase<
43 | 	Value,
44 | 	Options extends WordsOptions = {},
45 | > = DelimiterCase<Value, '_', ApplyDefaultOptions<WordsOptions, DefaultDelimiterCaseOptions, Options>>;
46 | 


--------------------------------------------------------------------------------
/source/snake-cased-properties-deep.d.ts:
--------------------------------------------------------------------------------
 1 | import type {DefaultDelimiterCaseOptions} from './delimiter-case.d.ts';
 2 | import type {DelimiterCasedPropertiesDeep} from './delimiter-cased-properties-deep.d.ts';
 3 | import type {ApplyDefaultOptions} from './internal/index.d.ts';
 4 | import type {WordsOptions} from './words.d.ts';
 5 | 
 6 | /**
 7 | Convert object properties to snake case recursively.
 8 | 
 9 | This can be useful when, for example, converting some API types from a different style.
10 | 
11 | @see SnakeCase
12 | @see SnakeCasedProperties
13 | 
14 | @example
15 | ```
16 | import type {SnakeCasedPropertiesDeep} from 'type-fest';
17 | 
18 | interface User {
19 | 	userId: number;
20 | 	userName: string;
21 | }
22 | 
23 | interface UserWithFriends {
24 | 	userInfo: User;
25 | 	userFriends: User[];
26 | }
27 | 
28 | const result: SnakeCasedPropertiesDeep<UserWithFriends> = {
29 | 	user_info: {
30 | 		user_id: 1,
31 | 		user_name: 'Tom',
32 | 	},
33 | 	user_friends: [
34 | 		{
35 | 			user_id: 2,
36 | 			user_name: 'Jerry',
37 | 		},
38 | 		{
39 | 			user_id: 3,
40 | 			user_name: 'Spike',
41 | 		},
42 | 	],
43 | };
44 | 
45 | const splitOnNumbers: SnakeCasedPropertiesDeep<{line1: { line2: [{ line3: string }] }}, {splitOnNumbers: true}> = {
46 | 	line_1: {
47 | 		line_2: [
48 | 			{
49 | 				line_3: 'string',
50 | 			},
51 | 		],
52 | 	},
53 | };
54 | ```
55 | 
56 | @category Change case
57 | @category Template literal
58 | @category Object
59 | */
60 | export type SnakeCasedPropertiesDeep<
61 | 	Value,
62 | 	Options extends WordsOptions = {},
63 | > = DelimiterCasedPropertiesDeep<Value, '_', ApplyDefaultOptions<WordsOptions, DefaultDelimiterCaseOptions, Options>>;
64 | 


--------------------------------------------------------------------------------
/source/snake-cased-properties.d.ts:
--------------------------------------------------------------------------------
 1 | import type {DefaultDelimiterCaseOptions} from './delimiter-case.d.ts';
 2 | import type {DelimiterCasedProperties} from './delimiter-cased-properties.d.ts';
 3 | import type {ApplyDefaultOptions} from './internal/index.d.ts';
 4 | import type {WordsOptions} from './words.d.ts';
 5 | 
 6 | /**
 7 | Convert object properties to snake case but not recursively.
 8 | 
 9 | This can be useful when, for example, converting some API types from a different style.
10 | 
11 | @see SnakeCase
12 | @see SnakeCasedPropertiesDeep
13 | 
14 | @example
15 | ```
16 | import type {SnakeCasedProperties} from 'type-fest';
17 | 
18 | interface User {
19 | 	userId: number;
20 | 	userName: string;
21 | }
22 | 
23 | const result: SnakeCasedProperties<User> = {
24 | 	user_id: 1,
25 | 	user_name: 'Tom',
26 | };
27 | 
28 | const splitOnNumbers: SnakeCasedProperties<{line1: string}, {splitOnNumbers: true}> = {
29 | 	'line_1': 'string',
30 | };
31 | ```
32 | 
33 | @category Change case
34 | @category Template literal
35 | @category Object
36 | */
37 | export type SnakeCasedProperties<
38 | 	Value,
39 | 	Options extends WordsOptions = {},
40 | > = DelimiterCasedProperties<Value, '_', ApplyDefaultOptions<WordsOptions, DefaultDelimiterCaseOptions, Options>>;
41 | 


--------------------------------------------------------------------------------
/source/string-repeat.d.ts:
--------------------------------------------------------------------------------
 1 | import type {IsNumericLiteral} from './is-literal.d.ts';
 2 | import type {IsNegative} from './numeric.d.ts';
 3 | 
 4 | /**
 5 | Returns a new string which contains the specified number of copies of a given string, just like `String#repeat()`.
 6 | 
 7 | @example
 8 | ```
 9 | import {StringRepeat} from 'type-fest';
10 | 
11 | declare function stringRepeat<
12 | 	Input extends string,
13 | 	Count extends number
14 | >(input: Input, count: Count): StringRepeat<Input, Count>;
15 | 
16 | // The return type is the exact string literal, not just `string`.
17 | 
18 | stringRepeat('foo', 2);
19 | //=> 'foofoo'
20 | 
21 | stringRepeat('=', 3);
22 | //=> '==='
23 | ```
24 | 
25 | @category String
26 | @category Template literal
27 | */
28 | export type StringRepeat<
29 | 	Input extends string,
30 | 	Count extends number,
31 | > = StringRepeatHelper<Input, Count>;
32 | 
33 | type StringRepeatHelper<
34 | 	Input extends string,
35 | 	Count extends number,
36 | 	Counter extends never[] = [],
37 | 	Accumulator extends string = '',
38 | > =
39 | 	IsNegative<Count> extends true
40 | 		? never
41 | 		: Input extends ''
42 | 			? ''
43 | 			: Count extends Counter['length']
44 | 				? Accumulator
45 | 				: IsNumericLiteral<Count> extends false
46 | 					? string
47 | 					: StringRepeatHelper<Input, Count, [...Counter, never], `${Accumulator}${Input}`>;
48 | 


--------------------------------------------------------------------------------
/source/string-slice.d.ts:
--------------------------------------------------------------------------------
 1 | import type {Join} from './join.d.ts';
 2 | import type {ArraySlice} from './array-slice.d.ts';
 3 | import type {StringToArray} from './internal/index.d.ts';
 4 | 
 5 | /**
 6 | Returns a string slice of a given range, just like `String#slice()`.
 7 | 
 8 | @see {ArraySlice}
 9 | 
10 | @example
11 | ```
12 | import type {StringSlice} from 'type-fest';
13 | 
14 | StringSlice<'abcde', 0, 2>;
15 | //=> 'ab'
16 | 
17 | StringSlice<'abcde', 1>;
18 | //=> 'bcde'
19 | 
20 | StringSlice<'abcde', 0, -1>;
21 | //=> 'abcd'
22 | 
23 | StringSlice<'abcde', -2, -1>;
24 | //=> 'd'
25 | ```
26 | 
27 | @category String
28 | */
29 | export type StringSlice<
30 | 	S extends string,
31 | 	Start extends number = 0,
32 | 	End extends number = StringToArray<S>['length'],
33 | > = string extends S
34 | 	? string
35 | 	: ArraySlice<StringToArray<S>, Start, End> extends infer R extends readonly string[]
36 | 		? Join<R, ''>
37 | 		: never;
38 | 


--------------------------------------------------------------------------------
/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 type {Stringified} from 'type-fest';
 9 | 
10 | type Car = {
11 | 	model: string;
12 | 	speed: number;
13 | }
14 | 
15 | const carForm: Stringified<Car> = {
16 | 	model: 'Foo',
17 | 	speed: '101'
18 | };
19 | ```
20 | 
21 | @category Object
22 | */
23 | export type Stringified<ObjectType> = {[KeyType in keyof ObjectType]: string};
24 | 


--------------------------------------------------------------------------------
/source/tagged-union.d.ts:
--------------------------------------------------------------------------------
 1 | /**
 2 | Create a union of types that share a common discriminant property.
 3 | 
 4 | Use-case: A shorter way to declare tagged unions with multiple members.
 5 | 
 6 | @example
 7 | ```
 8 | import type {TaggedUnion} from 'type-fest';
 9 | 
10 | type Tagged<Fields extends Record<string, unknown> = TaggedUnion<'type', Fields>
11 | 
12 | // The TaggedUnion utility reduces the amount of boilerplate needed to create a tagged union with multiple members, making the code more concise.
13 | type EventMessage = Tagged<{
14 | 	OpenExternalUrl: {
15 | 		url: string;
16 | 		id: number;
17 | 		language: string;
18 | 	};
19 | 	ToggleBackButtonVisibility: {
20 | 		visible: boolean;
21 | 	};
22 | 	PurchaseButtonPressed: {
23 | 		price: number;
24 | 		time: Date;
25 | 	};
26 | 	NavigationStateChanged: {
27 | 		navigation?: string;
28 | 	};
29 | }>;
30 | 
31 | // Here is the same type created without this utility.
32 | type EventMessage =
33 | 	| {
34 | 		type: 'OpenExternalUrl';
35 | 		url: string;
36 | 		id: number;
37 | 		language: string;
38 | 	}
39 | 	| {type: 'ToggleBackButtonVisibility'; visible: boolean}
40 | 	| {type: 'PurchaseButtonPressed'; price: number; time: Date}
41 | 	| {type: 'NavigationStateChanged'; navigation?: string};
42 | ```
43 | 
44 | @category Utilities
45 | */
46 | export type TaggedUnion<
47 | 	TagKey extends string,
48 | 	UnionMembers extends Record<string, Record<string, unknown>>,
49 | > = {
50 | 	[Name in keyof UnionMembers]: {[Key in TagKey]: Name} & UnionMembers[Name];
51 | }[keyof UnionMembers];
52 | 


--------------------------------------------------------------------------------
/source/trim.d.ts:
--------------------------------------------------------------------------------
 1 | import type {Whitespace} from './internal/index.d.ts';
 2 | 
 3 | /**
 4 | Remove spaces from the left side.
 5 | */
 6 | type TrimLeft<V extends string> = V extends `${Whitespace}${infer R}` ? TrimLeft<R> : V;
 7 | 
 8 | /**
 9 | Remove spaces from the right side.
10 | */
11 | type TrimRight<V extends string> = V extends `${infer R}${Whitespace}` ? TrimRight<R> : V;
12 | 
13 | /**
14 | Remove leading and trailing spaces from a string.
15 | 
16 | @example
17 | ```
18 | import type {Trim} from 'type-fest';
19 | 
20 | Trim<' foo '>
21 | //=> 'foo'
22 | ```
23 | 
24 | @category String
25 | @category Template literal
26 | */
27 | export type Trim<V extends string> = TrimLeft<TrimRight<V>>;
28 | 


--------------------------------------------------------------------------------
/source/tuple-to-object.d.ts:
--------------------------------------------------------------------------------
 1 | import type {IsTuple} from './is-tuple.d.ts';
 2 | import type {UnknownArray} from './unknown-array.d.ts';
 3 | import type {IsAny} from './is-any.d.ts';
 4 | import type {If} from './if.d.ts';
 5 | 
 6 | /**
 7 | Transforms a tuple into an object, mapping each tuple index to its corresponding type as a key-value pair.
 8 | 
 9 | Note: Tuple labels are [lost in the transformation process](https://stackoverflow.com/a/70398429/11719314). For example, `TupleToObject<[x: number, y: number]>` produces `{0: number; 1: number}`, and not `{x: number; y: number}`.
10 | 
11 | @example
12 | ```
13 | type Example1 = TupleToObject<[number, string, boolean]>;
14 | //=> { 0: number; 1: string; 2: boolean }
15 | 
16 | // Tuples with optional indices
17 | type Example2 = TupleToObject<[number, string?, boolean?]>;
18 | //=> { 0: number; 1?: string; 2?: boolean }
19 | 
20 | // Readonly tuples
21 | type Example3 = TupleToObject<readonly [number, string?]>;
22 | //=> { readonly 0: number; readonly 1?: string }
23 | 
24 | // Non-tuple arrays get transformed into index signatures
25 | type Example4 = TupleToObject<string[]>;
26 | //=> { [x: number]: string }
27 | 
28 | // Tuples with rest elements
29 | type Example5 = TupleToObject<[number, string, ...boolean[]]>;
30 | //=> { [x: number]: number | string | boolean; 0: number; 1: string }
31 | 
32 | // Tuple labels are not preserved
33 | type Example6 = TupleToObject<[x: number, y: number]>;
34 | //=> { 0: number; 1: number }
35 | ```
36 | 
37 | @category Array
38 | */
39 | export type TupleToObject<TArray extends UnknownArray> = If<IsAny<TArray>, any, {
40 | 	[
41 | 	Key in keyof TArray as Key & (`${number}` | (IsTuple<TArray> extends true ? never : number))
42 | 	]: TArray[Key];
43 | }>;
44 | 


--------------------------------------------------------------------------------
/source/typed-array.d.ts:
--------------------------------------------------------------------------------
 1 | /**
 2 | Matches any [typed array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray), like `Uint8Array` or `Float64Array`.
 3 | 
 4 | @category Array
 5 | */
 6 | export type TypedArray =
 7 | 	| Int8Array
 8 | 	| Uint8Array
 9 | 	| Uint8ClampedArray
10 | 	| Int16Array
11 | 	| Uint16Array
12 | 	| Int32Array
13 | 	| Uint32Array
14 | 	| Float32Array
15 | 	| Float64Array
16 | 	| BigInt64Array
17 | 	| BigUint64Array;
18 | 


--------------------------------------------------------------------------------
/source/union-to-tuple.d.ts:
--------------------------------------------------------------------------------
 1 | import type {IsNever} from './is-never.d.ts';
 2 | import type {UnionToIntersection} from './union-to-intersection.d.ts';
 3 | 
 4 | /**
 5 | Returns the last element of a union type.
 6 | 
 7 | @example
 8 | ```
 9 | type Last = LastOfUnion<1 | 2 | 3>;
10 | //=> 3
11 | ```
12 | */
13 | type LastOfUnion<T> =
14 | UnionToIntersection<T extends any ? () => T : never> extends () => (infer R)
15 | 	? R
16 | 	: never;
17 | 
18 | /**
19 | Convert a union type into an unordered tuple type of its elements.
20 | 
21 | "Unordered" means the elements of the tuple are not guaranteed to be in the same order as in the union type. The arrangement can appear random and may change at any time.
22 | 
23 | This can be useful when you have objects with a finite set of keys and want a type defining only the allowed keys, but do not want to repeat yourself.
24 | 
25 | @example
26 | ```
27 | import type {UnionToTuple} from 'type-fest';
28 | 
29 | type Numbers = 1 | 2 | 3;
30 | type NumbersTuple = UnionToTuple<Numbers>;
31 | //=> [1, 2, 3]
32 | ```
33 | 
34 | @example
35 | ```
36 | import type {UnionToTuple} from 'type-fest';
37 | 
38 | const pets = {
39 |   dog: '🐶',
40 |   cat: '🐱',
41 |   snake: '🐍',
42 | };
43 | 
44 | type Pet = keyof typeof pets;
45 | //=> 'dog' | 'cat' | 'snake'
46 | 
47 | const petList = Object.keys(pets) as UnionToTuple<Pet>;
48 | //=> ['dog', 'cat', 'snake']
49 | ```
50 | 
51 | @category Array
52 | */
53 | export type UnionToTuple<T, L = LastOfUnion<T>> =
54 | IsNever<T> extends false
55 | 	? [...UnionToTuple<Exclude<T, L>>, L]
56 | 	: [];
57 | 


--------------------------------------------------------------------------------
/source/unknown-array.d.ts:
--------------------------------------------------------------------------------
 1 | /**
 2 | Represents an array with `unknown` value.
 3 | 
 4 | Use case: You want a type that all arrays can be assigned to, but you don't care about the value.
 5 | 
 6 | @example
 7 | ```
 8 | import type {UnknownArray} from 'type-fest';
 9 | 
10 | type IsArray<T> = T extends UnknownArray ? true : false;
11 | 
12 | type A = IsArray<['foo']>;
13 | //=> true
14 | 
15 | type B = IsArray<readonly number[]>;
16 | //=> true
17 | 
18 | type C = IsArray<string>;
19 | //=> false
20 | ```
21 | 
22 | @category Type
23 | @category Array
24 | */
25 | export type UnknownArray = readonly unknown[];
26 | 


--------------------------------------------------------------------------------
/source/unknown-map.d.ts:
--------------------------------------------------------------------------------
 1 | /**
 2 | Represents a map with `unknown` key and value.
 3 | 
 4 | Use case: You want a type that all maps can be assigned to, but you don't care about the value.
 5 | 
 6 | @example
 7 | ```
 8 | import type {UnknownMap} from 'type-fest';
 9 | 
10 | type IsMap<T> = T extends UnknownMap ? true : false;
11 | 
12 | type A = IsMap<Map<string, number>>;
13 | //=> true
14 | 
15 | type B = IsMap<ReadonlyMap<number, string>>;
16 | //=> true
17 | 
18 | type C = IsMap<string>;
19 | //=> false
20 | ```
21 | 
22 | @category Type
23 | */
24 | export type UnknownMap = ReadonlyMap<unknown, unknown>;
25 | 


--------------------------------------------------------------------------------
/source/unknown-record.d.ts:
--------------------------------------------------------------------------------
 1 | /**
 2 | Represents an object with `unknown` value. You probably want this instead of `{}`.
 3 | 
 4 | Use case: You have an object whose keys and values are unknown to you.
 5 | 
 6 | @example
 7 | ```
 8 | import type {UnknownRecord} from 'type-fest';
 9 | 
10 | function toJson(object: UnknownRecord) {
11 | 	return JSON.stringify(object);
12 | }
13 | 
14 | toJson({hello: 'world'});
15 | //=> '{"hello":"world"}'
16 | 
17 | function isObject(value: unknown): value is UnknownRecord {
18 | 	return typeof value === 'object' && value !== null;
19 | }
20 | 
21 | isObject({hello: 'world'});
22 | //=> true
23 | 
24 | isObject('hello');
25 | //=> false
26 | ```
27 | 
28 | @category Type
29 | @category Object
30 | */
31 | export type UnknownRecord = Record<PropertyKey, unknown>;
32 | 


--------------------------------------------------------------------------------
/source/unknown-set.d.ts:
--------------------------------------------------------------------------------
 1 | /**
 2 | Represents a set with `unknown` value.
 3 | 
 4 | Use case: You want a type that all sets can be assigned to, but you don't care about the value.
 5 | 
 6 | @example
 7 | ```
 8 | import type {UnknownSet} from 'type-fest';
 9 | 
10 | type IsSet<T> = T extends UnknownSet ? true : false;
11 | 
12 | type A = IsSet<Set<string>>;
13 | //=> true
14 | 
15 | type B = IsSet<ReadonlySet<number>>;
16 | //=> true
17 | 
18 | type C = IsSet<string>;
19 | //=> false
20 | ```
21 | 
22 | @category Type
23 | */
24 | export type UnknownSet = ReadonlySet<unknown>;
25 | 


--------------------------------------------------------------------------------
/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 data = require('./data.json');
18 | 
19 | export function getData(name: string): ValueOf<typeof data> {
20 | 	return data[name];
21 | }
22 | 
23 | export function onlyBar(name: string): ValueOf<typeof data, 'bar'> {
24 | 	return data[name];
25 | }
26 | 
27 | // file.ts
28 | import {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 | @category Object
41 | */
42 | export type ValueOf<ObjectType, ValueType extends keyof ObjectType = keyof ObjectType> = ObjectType[ValueType];
43 | 


--------------------------------------------------------------------------------
/source/writable-keys-of.d.ts:
--------------------------------------------------------------------------------
 1 | import type {IsEqual} from './is-equal.d.ts';
 2 | 
 3 | /**
 4 | Extract all writable keys from the given type.
 5 | 
 6 | This is useful when you want to create a new type that contains writable keys only.
 7 | 
 8 | @example
 9 | ```
10 | import type {WritableKeysOf} from 'type-fest';
11 | 
12 | interface User {
13 | 	name: string;
14 | 	surname: string;
15 | 	readonly id: number;
16 | }
17 | 
18 | type UpdateRequest<Entity extends object> = Pick<Entity, WritableKeysOf<Entity>>;
19 | 
20 | const update1: UpdateRequest<User> = {
21 | 	name: 'Alice',
22 | 	surname: 'Acme',
23 | };
24 | ```
25 | 
26 | @category Utilities
27 | */
28 | export type WritableKeysOf<T extends object> =
29 | 	T extends unknown // For distributing `T`
30 | 		? (keyof {
31 | 			[P in keyof T as IsEqual<{[Q in P]: T[P]}, {readonly [Q in P]: T[P]}> extends false ? P : never]: never
32 | 		}) & keyof T // Intersect with `keyof T` to ensure result of `WritableKeysOf<T>` is always assignable to `keyof T`
33 | 		: never; // Should never happen
34 | 


--------------------------------------------------------------------------------
/test-d/and.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {And} from '../source/and.d.ts';
 3 | 
 4 | expectType<And<true, true>>(true);
 5 | expectType<And<true, false>>(false);
 6 | expectType<And<false, true>>(false);
 7 | expectType<And<false, false>>(false);
 8 | 
 9 | expectType<And<true, boolean>>({} as boolean);
10 | expectType<And<boolean, true>>({} as boolean);
11 | expectType<And<false, boolean>>(false);
12 | expectType<And<boolean, false>>(false);
13 | expectType<And<boolean, boolean>>({} as boolean);
14 | 
15 | // Boundary cases
16 | expectType<And<any, true>>({} as boolean);
17 | expectType<And<true, any>>({} as boolean);
18 | expectType<And<any, false>>(false);
19 | expectType<And<false, any>>(false);
20 | expectType<And<any, boolean>>({} as boolean);
21 | expectType<And<boolean, any>>({} as boolean);
22 | expectType<And<any, any>>({} as boolean);
23 | 
24 | expectType<And<never, true>>(false);
25 | expectType<And<true, never>>(false);
26 | expectType<And<never, false>>(false);
27 | expectType<And<false, never>>(false);
28 | expectType<And<never, boolean>>(false);
29 | expectType<And<boolean, never>>(false);
30 | expectType<And<never, never>>(false);
31 | 


--------------------------------------------------------------------------------
/test-d/array-indices.ts:
--------------------------------------------------------------------------------
 1 | import {expectNotAssignable, expectType, expectAssignable} from 'tsd';
 2 | import type {ArrayIndices} from '../index.d.ts';
 3 | 
 4 | const values = ['a', 'b', 'c'] as const;
 5 | type ValueKeys = ArrayIndices<typeof values>;
 6 | 
 7 | declare const test: 0 | 1 | 2;
 8 | expectType<ValueKeys>(test);
 9 | 
10 | expectAssignable<ValueKeys>(0);
11 | expectAssignable<ValueKeys>(1);
12 | expectAssignable<ValueKeys>(2);
13 | 
14 | expectNotAssignable<ValueKeys>(-1);
15 | expectNotAssignable<ValueKeys>(3);
16 | 
17 | type TupleKeys = ArrayIndices<['a', 2]>;
18 | 
19 | declare const testTuple: 0 | 1;
20 | expectType<TupleKeys>(testTuple);
21 | 
22 | expectAssignable<TupleKeys>(0);
23 | expectAssignable<TupleKeys>(1);
24 | 
25 | expectNotAssignable<TupleKeys>(-1);
26 | expectNotAssignable<TupleKeys>(2);
27 | 


--------------------------------------------------------------------------------
/test-d/array-splice.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {ArraySplice} from '../index.d.ts';
 3 | 
 4 | // Test fixed array
 5 | type TestTuple = ['a', 'b', 'c', 'd'];
 6 | 
 7 | declare const tuple0: ArraySplice<TestTuple, 2, 1>;
 8 | expectType<['a', 'b', 'd']>(tuple0);
 9 | 
10 | declare const tuple1: ArraySplice<TestTuple, 2, 1, ['e', 'f']>;
11 | expectType<['a', 'b', 'e', 'f', 'd']>(tuple1);
12 | 
13 | declare const tuple2: ArraySplice<TestTuple, 2, 0, ['e', 'f']>;
14 | expectType<['a', 'b', 'e', 'f', 'c', 'd']>(tuple2);
15 | 
16 | declare const tuple3: ArraySplice<TestTuple, 0, 1>;
17 | expectType<['b', 'c', 'd']>(tuple3);
18 | 
19 | declare const tuple4: ArraySplice<TestTuple, 0, 1, ['e', 'f']>;
20 | expectType<['e', 'f', 'b', 'c', 'd']>(tuple4);
21 | 
22 | // Test variable array
23 | type TestArray = ['a', 'b', 'c', 'd', ...number[]];
24 | 
25 | declare const array0: ArraySplice<TestArray, 2, 1>;
26 | expectType<['a', 'b', 'd', ...number[]]>(array0);
27 | 
28 | declare const array1: ArraySplice<TestArray, 2, 1, ['e', 'f']>;
29 | expectType<['a', 'b', 'e', 'f', 'd', ...number[]]>(array1);
30 | 
31 | declare const array2: ArraySplice<TestArray, 6, 0, ['e', 'f']>;
32 | expectType<['a', 'b', 'c', 'd', number, number, 'e', 'f', ...number[]]>(array2);
33 | 


--------------------------------------------------------------------------------
/test-d/array-values.ts:
--------------------------------------------------------------------------------
 1 | import {expectNotAssignable, expectType, expectAssignable} from 'tsd';
 2 | import type {ArrayValues} from '../index.d.ts';
 3 | 
 4 | const values = ['a', 'b', 'c'] as const;
 5 | type Values = ArrayValues<typeof values>;
 6 | 
 7 | declare const test: 'a' | 'b' | 'c';
 8 | expectType<Values>(test);
 9 | 
10 | expectAssignable<Values>('a');
11 | expectAssignable<Values>('b');
12 | expectAssignable<Values>('c');
13 | 
14 | expectNotAssignable<Values>('');
15 | expectNotAssignable<Values>(0);
16 | 
17 | type TupleValues = ArrayValues<['1', 2, {c: true}]>;
18 | 
19 | declare const testTuple: '1' | 2 | {c: true};
20 | expectType<TupleValues>(testTuple);
21 | 
22 | expectAssignable<TupleValues>('1');
23 | expectAssignable<TupleValues>(2);
24 | expectAssignable<TupleValues>({c: true});
25 | 
26 | expectNotAssignable<TupleValues>({});
27 | expectNotAssignable<TupleValues>(1);
28 | expectNotAssignable<TupleValues>('2');
29 | 
30 | type AnyStringValues = ArrayValues<string[]>;
31 | expectAssignable<AnyStringValues>('');
32 | expectAssignable<AnyStringValues>('123');
33 | expectNotAssignable<AnyStringValues>(123);
34 | expectNotAssignable<AnyStringValues>(undefined);
35 | expectNotAssignable<AnyStringValues>(null);
36 | 


--------------------------------------------------------------------------------
/test-d/arrayable.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {Arrayable} from '../index.d.ts';
 3 | 
 4 | declare const unknown: unknown;
 5 | 
 6 | expectType<Arrayable<string>>(unknown as string | string[]);
 7 | expectType<Arrayable<string | {foo: number}>>(unknown as (string | {foo: number}) | Array<string | {foo: number}>);
 8 | expectType<Arrayable<never>>(unknown as /* never | */ never[]);
 9 | expectType<Arrayable<string[]>>(unknown as string[] | string[][]);
10 | 
11 | // Test for issue https://github.com/sindresorhus/type-fest/issues/952
12 | type Item = number;
13 | function castArray1(value: Arrayable<Item>): Item[] {
14 | 	return Array.isArray(value) ? value : [value];
15 | }
16 | 
17 | expectType<Item[]>(unknown as ReturnType<typeof castArray1>);
18 | 
19 | function castArray2<T>(value: Arrayable<T>): T[] {
20 | 	return Array.isArray(value) ? value : [value];
21 | }
22 | 
23 | expectType<number[]>(castArray2(1));
24 | expectType<number[]>(castArray2([1, 2, 3]));
25 | 


--------------------------------------------------------------------------------
/test-d/async-return-type.ts:
--------------------------------------------------------------------------------
 1 | import {expectNotAssignable, expectType} from 'tsd';
 2 | import type {AsyncReturnType} from '../index.d.ts';
 3 | 
 4 | async function asyncFunction(): Promise<number> {
 5 | 	return 2;
 6 | }
 7 | 
 8 | type Value = AsyncReturnType<typeof asyncFunction>;
 9 | 
10 | asyncFunction().then(value => { // eslint-disable-line unicorn/prefer-top-level-await, @typescript-eslint/no-floating-promises
11 | 	expectType<Value>(value);
12 | 	expectNotAssignable<string>(value);
13 | });
14 | 
15 | function asyncPromiseLike(): PromiseLike<number> {
16 | 	return Promise.resolve(2);
17 | }
18 | 
19 | type ValuePromiseLike = AsyncReturnType<typeof asyncPromiseLike>;
20 | 
21 | asyncPromiseLike().then(value => { // eslint-disable-line unicorn/prefer-top-level-await, @typescript-eslint/no-floating-promises
22 | 	expectType<ValuePromiseLike>(value);
23 | 	expectNotAssignable<string>(value);
24 | });
25 | 


--------------------------------------------------------------------------------
/test-d/asyncify.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {Asyncify} from '../index.d.ts';
 3 | 
 4 | declare function getFooSync(name: string): RegExp;
 5 | declare function getFooWithThisArgumentSync(this: Date, name: string): RegExp;
 6 | 
 7 | // Basic usage.
 8 | declare const getFooAsync1: Asyncify<typeof getFooSync>;
 9 | expectType<(name: string) => Promise<RegExp>>(getFooAsync1);
10 | 
11 | // Noops with async functions.
12 | declare const getFooAsync2: Asyncify<typeof getFooAsync1>;
13 | expectType<typeof getFooAsync1>(getFooAsync2);
14 | 
15 | // Respects `thisArg`.
16 | declare const getFooWithThisArgumentAsync1: Asyncify<typeof getFooWithThisArgumentSync>;
17 | const callResult = getFooWithThisArgumentAsync1.call(new Date(), 'foo');
18 | expectType<Promise<RegExp>>(callResult);
19 | 
20 | // @ts-expect-error
21 | // eslint-disable-next-line @typescript-eslint/no-floating-promises
22 | getFooWithThisArgumentAsync1.call('not-date', 'foo');
23 | 


--------------------------------------------------------------------------------
/test-d/camel-cased-properties.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {CamelCasedProperties} from '../index.d.ts';
 3 | 
 4 | declare const foo: CamelCasedProperties<{A: number; B: {C: string}}>;
 5 | expectType<{a: number; b: {C: string}}>(foo);
 6 | 
 7 | declare const bar: CamelCasedProperties<Array<{helloWorld: string}>>;
 8 | expectType<Array<{helloWorld: string}>>(bar);
 9 | 
10 | declare const fooBar: CamelCasedProperties<() => {a: string}>;
11 | expectType<() => {a: string}>(fooBar);
12 | 
13 | declare const baz: CamelCasedProperties<{fooBAR: number; BARFoo: string}, {preserveConsecutiveUppercase: true}>;
14 | expectType<{fooBAR: number; bARFoo: string}>(baz);
15 | 
16 | declare const biz: CamelCasedProperties<{fooBAR: number; BARFoo: string}>;
17 | expectType<{fooBar: number; barFoo: string}>(biz);
18 | 
19 | // Verify example
20 | type User = {
21 | 	UserId: number;
22 | 	UserName: string;
23 | };
24 | 
25 | const result: CamelCasedProperties<User> = {
26 | 	userId: 1,
27 | 	userName: 'Tom',
28 | };
29 | expectType<CamelCasedProperties<User>>(result);
30 | 


--------------------------------------------------------------------------------
/test-d/conditional-except.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {ConditionalExcept, Primitive} from '../index.d.ts';
 3 | 
 4 | class Awesome {
 5 | 	name!: string;
 6 | 	successes!: number;
 7 | 	failures!: bigint;
 8 | 
 9 | 	run(): void {
10 | 		// Empty
11 | 	}
12 | }
13 | 
14 | type Example = {
15 | 	a: string;
16 | 	b?: string | number;
17 | 	c?: string;
18 | 	d: Record<string, unknown>;
19 | };
20 | 
21 | declare const exampleConditionalExcept: ConditionalExcept<Example, string>;
22 | expectType<{b?: string | number; c?: string; d: Record<string, unknown>}>(exampleConditionalExcept);
23 | 
24 | declare const awesomeConditionalExcept: ConditionalExcept<Awesome, Primitive>;
25 | expectType<{run: () => void}>(awesomeConditionalExcept);
26 | 
27 | declare const exampleConditionalExceptWithUndefined: ConditionalExcept<Example, string | undefined>;
28 | expectType<{b?: string | number; d: Record<string, unknown>}>(exampleConditionalExceptWithUndefined);
29 | 


--------------------------------------------------------------------------------
/test-d/conditional-pick.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {ConditionalPick, Primitive} from '../index.d.ts';
 3 | 
 4 | class Awesome {
 5 | 	name!: string;
 6 | 	successes!: number;
 7 | 	failures!: bigint;
 8 | 
 9 | 	run(): void {
10 | 		// Empty
11 | 	}
12 | }
13 | 
14 | type Example = {
15 | 	a: string;
16 | 	b?: string | number;
17 | 	c?: string;
18 | 	d: Record<string, unknown>;
19 | };
20 | 
21 | declare const exampleConditionalPick: ConditionalPick<Example, string>;
22 | expectType<{a: string}>(exampleConditionalPick);
23 | 
24 | declare const awesomeConditionalPick: ConditionalPick<Awesome, Primitive>;
25 | expectType<{name: string; successes: number; failures: bigint}>(awesomeConditionalPick);
26 | 
27 | declare const exampleConditionalPickWithUndefined: ConditionalPick<Example, string | undefined>;
28 | expectType<{a: string; c?: string}>(exampleConditionalPickWithUndefined);
29 | 


--------------------------------------------------------------------------------
/test-d/conditional-simplify.ts:
--------------------------------------------------------------------------------
 1 | import {expectNotAssignable, expectType} from 'tsd';
 2 | import type {ConditionalSimplify} from '../index.d.ts';
 3 | 
 4 | type Position = {top: number; left: number};
 5 | type Size = {width: number; height: number};
 6 | 
 7 | // In your editor, hovering over `PositionAndSizeSimplified` will show a simplified object with all the properties.
 8 | type PositionAndSizeIntersection = Position & Size;
 9 | type PositionAndSizeSimplified = ConditionalSimplify<PositionAndSizeIntersection>;
10 | 
11 | const position = {top: 120, left: 240};
12 | const size = {width: 480, height: 600};
13 | const positionAndSize = {...position, ...size};
14 | expectType<PositionAndSizeSimplified>(positionAndSize);
15 | 
16 | // Exclude function type to be simplified.
17 | type SomeFunction = (type: string) => string;
18 | type SimplifiedFunctionFail = ConditionalSimplify<SomeFunction>; // Return '{}'
19 | type SimplifiedFunctionPass = ConditionalSimplify<SomeFunction, Function>; // Return '(type: string) => string'
20 | 
21 | declare const simplifiedFunctionFail: SimplifiedFunctionFail;
22 | declare const simplifiedFunctionPass: SimplifiedFunctionPass;
23 | 
24 | expectNotAssignable<SomeFunction>(simplifiedFunctionFail);
25 | expectType<SomeFunction>(simplifiedFunctionPass);
26 | 


--------------------------------------------------------------------------------
/test-d/delimiter-cased-properties.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {DelimiterCasedProperties} from '../index.d.ts';
 3 | 
 4 | declare const foo: DelimiterCasedProperties<{helloWorld: {fooBar: string}}, '/'>;
 5 | expectType<{'hello/world': {fooBar: string}}>(foo);
 6 | 
 7 | declare const bar: DelimiterCasedProperties<Array<{helloWorld: string}>, '-'>;
 8 | expectType<Array<{helloWorld: string}>>(bar);
 9 | 
10 | declare const fooBar: DelimiterCasedProperties<() => {a: string}, '-'>;
11 | expectType<() => {a: string}>(fooBar);
12 | 
13 | declare const withOptions: DelimiterCasedProperties<{helloWorld1: {fooBar: string}}, '.', {splitOnNumbers: true}>;
14 | expectType<{'hello.world.1': {fooBar: string}}>(withOptions);
15 | 
16 | // Verify example
17 | type User = {
18 | 	userId: number;
19 | 	userName: string;
20 | };
21 | const result: DelimiterCasedProperties<User, '-'> = {
22 | 	'user-id': 1,
23 | 	'user-name': 'Tom',
24 | };
25 | expectType<DelimiterCasedProperties<User, '-'>>(result);
26 | 


--------------------------------------------------------------------------------
/test-d/empty-object.ts:
--------------------------------------------------------------------------------
 1 | import {expectAssignable, expectType} from 'tsd';
 2 | import type {EmptyObject, IsEmptyObject} from '../index.d.ts';
 3 | 
 4 | declare let foo: EmptyObject;
 5 | 
 6 | expectAssignable<{}>(foo);
 7 | expectAssignable<{}>(foo = {});
 8 | 
 9 | // @ts-expect-error
10 | foo = [];
11 | // @ts-expect-error
12 | foo = {x: 1};
13 | // @ts-expect-error
14 | foo = 42;
15 | // @ts-expect-error
16 | foo = null;
17 | // @ts-expect-error
18 | foo.bar = 42;
19 | // @ts-expect-error
20 | foo.bar = {};
21 | 
22 | expectType<IsEmptyObject<{}>>(true);
23 | expectType<IsEmptyObject<typeof foo>>(true);
24 | 
25 | expectType<IsEmptyObject<[]>>(false);
26 | expectType<IsEmptyObject<null>>(false);
27 | expectType<IsEmptyObject<() => void>>(false);
28 | 
29 | type Union = EmptyObject | {id: number};
30 | 
31 | const bar: Union = {};
32 | // @ts-expect-error
33 | const _a: unknown = bar.id;
34 | 
35 | const baz: Union = {id: 42};
36 | expectType<{id: number}>(baz);
37 | 


--------------------------------------------------------------------------------
/test-d/enforce-optional.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {EnforceOptional} from '../source/enforce-optional.d.ts';
 3 | 
 4 | type Foo = {
 5 | 	a: string;
 6 | 	b?: string;
 7 | 	c: undefined;
 8 | 	d: number | undefined;
 9 | };
10 | 
11 | type EnforcedOptionalFoo = EnforceOptional<Foo>;
12 | 
13 | declare const enforcedOptionalFoo: EnforcedOptionalFoo;
14 | 
15 | expectType<{
16 | 	a: string;
17 | 	b?: string;
18 | 	c: undefined;
19 | 	d?: number;
20 | }>(enforcedOptionalFoo);
21 | 


--------------------------------------------------------------------------------
/test-d/except.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {Except} from '../index.d.ts';
 3 | 
 4 | declare const except: Except<{a: number; b: string}, 'b'>;
 5 | expectType<{a: number}>(except);
 6 | // @ts-expect-error
 7 | const _a: unknown = except.b;
 8 | 
 9 | const nonStrict = {
10 | 	a: 1,
11 | 	b: '2',
12 | };
13 | 
14 | const nonStrictAssignment: typeof except = nonStrict; // No error
15 | 
16 | declare const strictExcept: Except<{a: number; b: string}, 'b', {requireExactProps: true}>;
17 | 
18 | // @ts-expect-error
19 | const strictAssignment: typeof strictExcept = nonStrict;
20 | 
21 | // Generic properties
22 | type Example = {
23 | 	[key: string]: unknown;
24 | 	foo: number;
25 | 	bar: string;
26 | };
27 | 
28 | const test: Except<Example, 'bar', {requireExactProps: false}> = {foo: 123, bar: 'asdf'};
29 | expectType<number>(test.foo);
30 | expectType<unknown>(test['bar']);
31 | 


--------------------------------------------------------------------------------
/test-d/fixed-length-array.ts:
--------------------------------------------------------------------------------
 1 | import {expectAssignable, expectNotAssignable} from 'tsd';
 2 | import type {FixedLengthArray} from '../index.d.ts';
 3 | 
 4 | type FixedToThreeStrings = FixedLengthArray<string, 3>;
 5 | 
 6 | expectAssignable<FixedToThreeStrings>(['a', 'b', 'c']);
 7 | 
 8 | expectNotAssignable<FixedToThreeStrings>(['a', 'b', 123]);
 9 | expectNotAssignable<FixedToThreeStrings>(['a']);
10 | expectNotAssignable<FixedToThreeStrings>(['a', 'b']);
11 | expectNotAssignable<FixedToThreeStrings>(['a', 'b', 'c', 'd']);
12 | 


--------------------------------------------------------------------------------
/test-d/global-this.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {GlobalThis} from '../index.d.ts';
 3 | 
 4 | type ExtraProperties = GlobalThis & {
 5 | 	readonly GLOBAL_TOKEN: string;
 6 | };
 7 | 
 8 | // Verify `globalThis` can be cast to a type which extends `GlobalThis`.
 9 | expectType<string>((globalThis as ExtraProperties).GLOBAL_TOKEN);
10 | 
11 | // Verify that object literals cannot be cast to a type which extends `GlobalThis`.
12 | declare function consumeExtraProperties(extraProperties: ExtraProperties): void;
13 | // @ts-expect-error
14 | consumeExtraProperties(({something: 'value'}) as ExtraProperties);
15 | 


--------------------------------------------------------------------------------
/test-d/greater-than.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {GreaterThan} from '../index.d.ts';
 3 | import type {NegativeInfinity, PositiveInfinity} from '../source/numeric.d.ts';
 4 | 
 5 | declare const never: never;
 6 | 
 7 | expectType<GreaterThan<1, 2>>(false);
 8 | expectType<GreaterThan<2, 1>>(true);
 9 | expectType<GreaterThan<10, 2>>(true);
10 | expectType<GreaterThan<10, -2>>(true);
11 | expectType<GreaterThan<2, 2>>(false);
12 | expectType<GreaterThan<-2, -2>>(false);
13 | expectType<GreaterThan<-2, -3>>(true);
14 | expectType<GreaterThan<-2, number>>(never);
15 | 
16 | // === unions ===
17 | expectType<GreaterThan<100 | 200, 50>>(true);
18 | expectType<GreaterThan<25, -100 | -15 | 2 | 21>>(true);
19 | expectType<GreaterThan<10 | 15, -5 | 5>>(true);
20 | 
21 | expectType<GreaterThan<10, 50 | 100>>(false);
22 | expectType<GreaterThan<50 | 25 | 0 | -16, 100>>(false);
23 | expectType<GreaterThan<1 | 2 | 3, 3 | 4>>(false);
24 | 
25 | expectType<GreaterThan<-10, -90 | 90>>({} as boolean);
26 | expectType<GreaterThan<-16 | 16, 0>>({} as boolean);
27 | expectType<GreaterThan<-4 | 45, 20 | 30>>({} as boolean);
28 | expectType<GreaterThan<1 | -1 | 3, 0 | 2>>({} as boolean);
29 | 
30 | expectType<GreaterThan<PositiveInfinity, -999>>(true);
31 | expectType<GreaterThan<PositiveInfinity, 999>>(true);
32 | expectType<GreaterThan<999, PositiveInfinity>>(false);
33 | expectType<GreaterThan<999, NegativeInfinity>>(true);
34 | expectType<GreaterThan<-999, NegativeInfinity>>(true);
35 | expectType<GreaterThan<PositiveInfinity, PositiveInfinity>>(false);
36 | expectType<GreaterThan<NegativeInfinity, NegativeInfinity>>(false);
37 | expectType<GreaterThan<PositiveInfinity, NegativeInfinity>>(true);
38 | 


--------------------------------------------------------------------------------
/test-d/has-optional-keys.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {HasOptionalKeys} from '../index.d.ts';
 3 | 
 4 | type TestType1 = {
 5 | 	a: string;
 6 | 	b?: boolean;
 7 | };
 8 | 
 9 | type TestType2 = {
10 | 	a?: string;
11 | 	b?: boolean;
12 | };
13 | 
14 | type TestType3 = {
15 | 	a: string;
16 | 	b: boolean;
17 | };
18 | 
19 | type HasOptionalKeys1 = HasOptionalKeys<TestType1>;
20 | type HasOptionalKeys2 = HasOptionalKeys<TestType2>;
21 | type HasOptionalKeys3 = HasOptionalKeys<TestType3>;
22 | 
23 | declare const test1: HasOptionalKeys1;
24 | declare const test2: HasOptionalKeys2;
25 | declare const test3: HasOptionalKeys3;
26 | 
27 | expectType<true>(test1);
28 | expectType<true>(test2);
29 | expectType<false>(test3);
30 | 


--------------------------------------------------------------------------------
/test-d/has-readonly-keys.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {HasReadonlyKeys} from '../index.d.ts';
 3 | 
 4 | type TestType1 = {
 5 | 	a: string;
 6 | 	readonly b: boolean;
 7 | };
 8 | 
 9 | type TestType2 = {
10 | 	readonly a: string;
11 | 	readonly b: boolean;
12 | };
13 | 
14 | type TestType3 = {
15 | 	a: string;
16 | 	b: boolean;
17 | };
18 | 
19 | type HasReadonlyKeys1 = HasReadonlyKeys<TestType1>;
20 | type HasReadonlyKeys2 = HasReadonlyKeys<TestType2>;
21 | type HasReadonlyKeys3 = HasReadonlyKeys<TestType3>;
22 | 
23 | declare const test1: HasReadonlyKeys1;
24 | declare const test2: HasReadonlyKeys2;
25 | declare const test3: HasReadonlyKeys3;
26 | 
27 | expectType<true>(test1);
28 | expectType<true>(test2);
29 | expectType<false>(test3);
30 | 


--------------------------------------------------------------------------------
/test-d/has-required-keys.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {HasRequiredKeys} from '../index.d.ts';
 3 | 
 4 | type TestType1 = {
 5 | 	a: string;
 6 | 	b?: boolean;
 7 | };
 8 | 
 9 | type TestType2 = {
10 | 	a?: string;
11 | 	b?: boolean;
12 | };
13 | 
14 | type TestType3 = {
15 | 	a: string;
16 | 	b: boolean;
17 | };
18 | 
19 | type HasRequiredKeys1 = HasRequiredKeys<TestType1>;
20 | type HasRequiredKeys2 = HasRequiredKeys<TestType2>;
21 | type HasRequiredKeys3 = HasRequiredKeys<TestType3>;
22 | 
23 | declare const test1: HasRequiredKeys1;
24 | declare const test2: HasRequiredKeys2;
25 | declare const test3: HasRequiredKeys3;
26 | 
27 | expectType<true>(test1);
28 | expectType<false>(test2);
29 | expectType<true>(test3);
30 | 


--------------------------------------------------------------------------------
/test-d/has-writable-keys.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {HasWritableKeys} from '../index.d.ts';
 3 | 
 4 | type TestType1 = {
 5 | 	a: string;
 6 | 	readonly b: boolean;
 7 | };
 8 | 
 9 | type TestType2 = {
10 | 	readonly a: string;
11 | 	readonly b: boolean;
12 | };
13 | 
14 | type TestType3 = {
15 | 	a: string;
16 | 	b: boolean;
17 | };
18 | 
19 | type HasWritableKeys1 = HasWritableKeys<TestType1>;
20 | type HasWritableKeys2 = HasWritableKeys<TestType2>;
21 | type HasWritableKeys3 = HasWritableKeys<TestType3>;
22 | 
23 | declare const test1: HasWritableKeys1;
24 | declare const test2: HasWritableKeys2;
25 | declare const test3: HasWritableKeys3;
26 | 
27 | expectType<true>(test1);
28 | expectType<false>(test2);
29 | expectType<true>(test3);
30 | 


--------------------------------------------------------------------------------
/test-d/if-any.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {IfAny} from '../index.d.ts';
 3 | 
 4 | declare const _any: any;
 5 | 
 6 | // `IfAny` should return `true`/`false` if only `T` is specified
 7 | expectType<IfAny<any>>(true);
 8 | expectType<IfAny<string>>(false);
 9 | expectType<IfAny<any, 'T', 'F'>>('T');
10 | expectType<IfAny<string, 'T', 'F'>>('F');
11 | 
12 | // Missing generic parameter
13 | // @ts-expect-error
14 | type A = IfAny;
15 | 


--------------------------------------------------------------------------------
/test-d/if-never.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {IfNever} from '../index.d.ts';
 3 | 
 4 | // `IfNever` should return `true`/`false` if only `T` is specified
 5 | expectType<IfNever<never>>(true);
 6 | expectType<IfNever<string>>(false);
 7 | expectType<IfNever<never, 'T', 'F'>>('T');
 8 | expectType<IfNever<string, 'T', 'F'>>('F');
 9 | 
10 | // Missing generic parameter
11 | // @ts-expect-error
12 | type A = IfNever;
13 | 


--------------------------------------------------------------------------------
/test-d/if-unknown.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {IfUnknown} from '../index.d.ts';
 3 | 
 4 | // `IfUnknown` should return `true`/`false` if only `T` is specified
 5 | expectType<IfUnknown<unknown>>(true);
 6 | expectType<IfUnknown<string>>(false);
 7 | expectType<IfUnknown<unknown, 'T', 'F'>>('T');
 8 | expectType<IfUnknown<string, 'T', 'F'>>('F');
 9 | 
10 | // Missing generic parameter
11 | // @ts-expect-error
12 | type A = IfUnknown;
13 | 


--------------------------------------------------------------------------------
/test-d/if.ts:
--------------------------------------------------------------------------------
1 | import {expectType} from 'tsd';
2 | import type {If} from '../source/if.d.ts';
3 | 
4 | expectType<string>({} as If<true, string, number>);
5 | expectType<number>({} as If<false, string, number>);
6 | expectType<string | number>({} as If<boolean, string, number>);
7 | expectType<string | number>({} as If<any, string, number>);
8 | expectType<number>({} as If<never, string, number>);
9 | 


--------------------------------------------------------------------------------
/test-d/int-closed-range.ts:
--------------------------------------------------------------------------------
 1 | import {expectType, expectAssignable} from 'tsd';
 2 | import type {IntClosedRange} from '../source/int-closed-range.d.ts';
 3 | 
 4 | declare const test: IntClosedRange<0, 5>;
 5 | expectType<0 | 1 | 2 | 3 | 4 | 5>(test);
 6 | 
 7 | declare const startTest: IntClosedRange<5, 10>;
 8 | expectType<5 | 6 | 7 | 8 | 9 | 10>(startTest);
 9 | 
10 | declare const stepTest1: IntClosedRange<10, 20, 2>;
11 | expectType<10 | 12 | 14 | 16 | 18 | 20>(stepTest1);
12 | 
13 | // Test for step > end - start
14 | declare const stepTest2: IntClosedRange<10, 20, 100>;
15 | expectType<10>(stepTest2);
16 | 
17 | type Int0_998 = IntClosedRange<0, 998>;
18 | declare const maxNumberTest: Int0_998;
19 | expectAssignable<number>(maxNumberTest);
20 | expectAssignable<Int0_998>(998);
21 | 


--------------------------------------------------------------------------------
/test-d/int-range.ts:
--------------------------------------------------------------------------------
 1 | import {expectType, expectAssignable} from 'tsd';
 2 | import type {IntRange} from '../source/int-range.d.ts';
 3 | 
 4 | declare const test: IntRange<0, 5>;
 5 | expectType<0 | 1 | 2 | 3 | 4>(test);
 6 | 
 7 | declare const startTest: IntRange<5, 10>;
 8 | expectType<5 | 6 | 7 | 8 | 9>(startTest);
 9 | 
10 | declare const stepTest1: IntRange<10, 20, 2>;
11 | expectType<10 | 12 | 14 | 16 | 18>(stepTest1);
12 | 
13 | // Test for step > end - start
14 | declare const stepTest2: IntRange<10, 20, 100>;
15 | expectType<10>(stepTest2);
16 | 
17 | declare const maxNumberTest: IntRange<0, 999>;
18 | expectAssignable<number>(maxNumberTest);
19 | 
20 | // Not yet supported.
21 | // declare const negative: IntRange<-1, 1>;
22 | // expectType<-1 | 0 | 1>(negative);
23 | 
24 | // declare const negative2: IntRange<1, -1>;
25 | // expectType<-1 | 0 | 1>(negative2);
26 | 


--------------------------------------------------------------------------------
/test-d/internal/build-tuple.ts:
--------------------------------------------------------------------------------
1 | import {expectType} from 'tsd';
2 | import type {BuildTuple} from '../../source/internal/index.d.ts';
3 | 
4 | expectType<BuildTuple<3, null>>([null, null, null]);
5 | expectType<BuildTuple<5, 0>>([0, 0, 0, 0, 0]);
6 | expectType<BuildTuple<0, 0>>([]);
7 | expectType<BuildTuple<2 | 3, 0>>({} as [0, 0] | [0, 0, 0]);
8 | expectType<BuildTuple<number, 0>>({} as Array<0>);
9 | 


--------------------------------------------------------------------------------
/test-d/internal/has-multiple-call-signatures.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {HasMultipleCallSignatures} from '../../source/internal/index.d.ts';
 3 | 
 4 | type Overloaded = {
 5 | 	(foo: number): string;
 6 | 	(foo: string, bar: number): number;
 7 | };
 8 | 
 9 | type Overloaded2 = {
10 | 	(foo: number | undefined): string;
11 | 	// eslint-disable-next-line @typescript-eslint/unified-signatures
12 | 	(foo: number): string;
13 | };
14 | 
15 | type Namespace = {
16 | 	(foo: number): string;
17 | 	baz: boolean[];
18 | };
19 | 
20 | expectType<true>({} as HasMultipleCallSignatures<Overloaded>);
21 | expectType<true>({} as HasMultipleCallSignatures<Overloaded2>);
22 | expectType<false>({} as HasMultipleCallSignatures<Namespace>);
23 | 


--------------------------------------------------------------------------------
/test-d/internal/if-not-any-or-never.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {IfNotAnyOrNever} from '../../source/internal/index.d.ts';
 3 | 
 4 | expectType<any>({} as IfNotAnyOrNever<any, string>);
 5 | expectType<never>({} as IfNotAnyOrNever<never, string>);
 6 | expectType<number>({} as IfNotAnyOrNever<any, string, number>);
 7 | expectType<number>({} as IfNotAnyOrNever<any, string, number, boolean>);
 8 | expectType<never>({} as IfNotAnyOrNever<never, string, number>);
 9 | expectType<boolean>({} as IfNotAnyOrNever<never, string, number, boolean>);
10 | expectType<number>({} as IfNotAnyOrNever<string, number>);
11 | expectType<number>({} as IfNotAnyOrNever<string | number, number, boolean>);
12 | expectType<number>({} as IfNotAnyOrNever<object, number, boolean, string>);
13 | 


--------------------------------------------------------------------------------
/test-d/internal/is-array-readonly.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {IsArrayReadonly} from '../../source/internal/index.d.ts';
 3 | 
 4 | // Non-readonly arrays
 5 | expectType<IsArrayReadonly<[]>>(false);
 6 | expectType<IsArrayReadonly<number[]>>(false);
 7 | expectType<IsArrayReadonly<[string, number?, ...string[]]>>(false);
 8 | expectType<IsArrayReadonly<[x: number, y: number, z?: number]>>(false);
 9 | expectType<IsArrayReadonly<[...string[], number, string]>>(false);
10 | 
11 | // Readonly arrays
12 | expectType<IsArrayReadonly<readonly []>>(true);
13 | expectType<IsArrayReadonly<readonly number[]>>(true);
14 | expectType<IsArrayReadonly<readonly [string, number?, ...string[]]>>(true);
15 | expectType<IsArrayReadonly<readonly [x: number, y: number, z?: number]>>(true);
16 | expectType<IsArrayReadonly<readonly [...string[], number, string]>>(true);
17 | 
18 | // Union
19 | expectType<IsArrayReadonly<[] | readonly []>>({} as boolean);
20 | expectType<IsArrayReadonly<[string, number] | readonly [string, number, ...string[]]>>({} as boolean);
21 | expectType<IsArrayReadonly<[] | [string, number]>>(false);
22 | expectType<IsArrayReadonly<readonly [] | readonly [string, number]>>(true);
23 | 
24 | // Boundary types
25 | expectType<IsArrayReadonly<any>>({} as boolean);
26 | expectType<IsArrayReadonly<never>>(false);
27 | 


--------------------------------------------------------------------------------
/test-d/internal/is-not-false.ts:
--------------------------------------------------------------------------------
 1 | /* eslint-disable @typescript-eslint/no-duplicate-type-constituents */
 2 | import {expectType} from 'tsd';
 3 | import type {IsNotFalse} from '../../source/internal/index.d.ts';
 4 | 
 5 | expectType<IsNotFalse<true>>(true);
 6 | expectType<IsNotFalse<boolean>>(true);
 7 | expectType<IsNotFalse<true | false>>(true);
 8 | expectType<IsNotFalse<true | false | false | false>>(true);
 9 | expectType<IsNotFalse<false>>(false);
10 | expectType<IsNotFalse<false | false>>(false);
11 | expectType<IsNotFalse<false | false | false | false>>(false);
12 | 


--------------------------------------------------------------------------------
/test-d/internal/is-number-like.ts:
--------------------------------------------------------------------------------
1 | import {expectType} from 'tsd';
2 | import type {IsNumberLike} from '../../source/internal/numeric.d.ts';
3 | 
4 | expectType<IsNumberLike<'1'>>(true);
5 | expectType<IsNumberLike<1>>(true);
6 | expectType<IsNumberLike<'-1.1'>>(true);
7 | expectType<IsNumberLike<-1.1>>(true);
8 | expectType<IsNumberLike<'foo'>>(false);
9 | 


--------------------------------------------------------------------------------
/test-d/internal/is-numeric.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {IsNumeric} from '../../source/internal/index.d.ts';
 3 | 
 4 | expectType<IsNumeric<''>>(false);
 5 | expectType<IsNumeric<'0'>>(true);
 6 | expectType<IsNumeric<'1'>>(true);
 7 | expectType<IsNumeric<'-1'>>(true);
 8 | expectType<IsNumeric<'123'>>(true);
 9 | expectType<IsNumeric<'1e2'>>(true);
10 | expectType<IsNumeric<'1.23'>>(true);
11 | expectType<IsNumeric<'123.456'>>(true);
12 | expectType<IsNumeric<'1.23e4'>>(true);
13 | expectType<IsNumeric<'1.23e-4'>>(true);
14 | expectType<IsNumeric<' '>>(false);
15 | expectType<IsNumeric<'\n'>>(false);
16 | expectType<IsNumeric<'\u{9}'>>(false);
17 | expectType<IsNumeric<' 1.2'>>(false);
18 | expectType<IsNumeric<'1 2'>>(false);
19 | expectType<IsNumeric<'1_200'>>(false);
20 | expectType<IsNumeric<' 1 '>>(false);
21 | 


--------------------------------------------------------------------------------
/test-d/internal/is-whitespace.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {IsWhitespace} from '../../source/internal/index.d.ts';
 3 | 
 4 | expectType<IsWhitespace<''>>(false);
 5 | expectType<IsWhitespace<' '>>(true);
 6 | expectType<IsWhitespace<'\n'>>(true);
 7 | expectType<IsWhitespace<'\u{9}'>>(true);
 8 | expectType<IsWhitespace<'a'>>(false);
 9 | expectType<IsWhitespace<'a '>>(false);
10 | expectType<IsWhitespace<'   '>>(true);
11 | expectType<IsWhitespace<' \t '>>(true);
12 | 


--------------------------------------------------------------------------------
/test-d/internal/not.ts:
--------------------------------------------------------------------------------
1 | import {expectType} from 'tsd';
2 | import type {Not} from '../../source/internal/index.d.ts';
3 | 
4 | expectType<Not<true>>(false);
5 | expectType<Not<false>>(true);
6 | expectType<Not<boolean>>({} as boolean);
7 | 


--------------------------------------------------------------------------------
/test-d/internal/number-absolute.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {NumberAbsolute} from '../../source/internal/index.d.ts';
 3 | import type {NegativeInfinity, PositiveInfinity} from '../../source/numeric.d.ts';
 4 | 
 5 | expectType<NumberAbsolute<3>>(3);
 6 | expectType<NumberAbsolute<-3>>(3);
 7 | expectType<NumberAbsolute<0>>(0);
 8 | expectType<NumberAbsolute<-0>>(0);
 9 | expectType<NumberAbsolute<NegativeInfinity>>(null! as PositiveInfinity);
10 | expectType<NumberAbsolute<PositiveInfinity>>(null! as PositiveInfinity);
11 | 


--------------------------------------------------------------------------------
/test-d/internal/object-value.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {ObjectValue} from '../../source/internal/index.d.ts';
 3 | 
 4 | type ObjectT = {
 5 | 	string: string;
 6 | 	0: number;
 7 | 	'1': number;
 8 | };
 9 | 
10 | declare const normal: ObjectValue<ObjectT, 'string'>;
11 | expectType<string>(normal);
12 | 
13 | declare const test0: ObjectValue<ObjectT, 0>;
14 | expectType<number>(test0);
15 | declare const teststring0: ObjectValue<ObjectT, '0'>;
16 | expectType<number>(teststring0);
17 | declare const test1: ObjectValue<ObjectT, 1>;
18 | expectType<number>(test1);
19 | declare const teststring1: ObjectValue<ObjectT, '1'>;
20 | expectType<number>(teststring1);
21 | 


--------------------------------------------------------------------------------
/test-d/internal/readonly-keys-of-union.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {ReadonlyKeysOfUnion} from '../../source/internal/index.d.ts';
 3 | 
 4 | declare const test1: ReadonlyKeysOfUnion<{readonly a: 1; b: 2}>;
 5 | expectType<'a'>(test1);
 6 | 
 7 | declare const test2: ReadonlyKeysOfUnion<{readonly a: 1; b?: 2} | {readonly c?: 3; d: 4}>;
 8 | expectType<'a' | 'c'>(test2);
 9 | 
10 | declare const test3: ReadonlyKeysOfUnion<{readonly a: 1; b?: 2} | {readonly c?: 3; d: 4} | {readonly c: 5} | {d: 6}>;
11 | expectType<'a' | 'c'>(test3);
12 | 
13 | // Returns `never` if there's no readonly key
14 | declare const test4: ReadonlyKeysOfUnion<{a: 1; b?: 2} | {c?: 3; d: 4}>;
15 | expectType<never>(test4);
16 | 
17 | // Works with index signatures
18 | declare const test5: ReadonlyKeysOfUnion<{readonly [x: string]: number; a: 1} | {readonly [x: symbol]: number; a: 2}>;
19 | expectType<string | number | symbol>(test5);
20 | 
21 | // Works with arrays
22 | declare const test7: ReadonlyKeysOfUnion<readonly string[] | readonly [number, number]>;
23 | expectType<number | typeof Symbol.unscopables | '0' | '1' | 'length'>(test7);
24 | 
25 | // Works with functions
26 | declare const test8: ReadonlyKeysOfUnion<(() => void) | {(): void; readonly a: 1}>;
27 | expectType<'a'>(test8);
28 | 


--------------------------------------------------------------------------------
/test-d/internal/require-none.ts:
--------------------------------------------------------------------------------
 1 | import {expectAssignable, expectNotAssignable} from 'tsd';
 2 | import type {RequireNone} from '../../source/internal/index.d.ts';
 3 | 
 4 | type NoneAllowed = RequireNone<'foo' | 'bar'>;
 5 | 
 6 | expectAssignable<NoneAllowed>({});
 7 | expectNotAssignable<NoneAllowed>({foo: 'foo'});
 8 | expectNotAssignable<NoneAllowed>({bar: 'bar'});
 9 | expectNotAssignable<NoneAllowed>({foo: 'foo', bar: 'bar'});
10 | 
11 | type SomeAllowed = Record<'bar', string> & RequireNone<'foo'>;
12 | 
13 | expectAssignable<SomeAllowed>({bar: 'bar'});
14 | expectNotAssignable<SomeAllowed>({foo: 'foo'});
15 | expectNotAssignable<SomeAllowed>({foo: 'foo', bar: 'bar'});
16 | 


--------------------------------------------------------------------------------
/test-d/internal/tuple-max.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {TupleMax} from '../../source/internal/index.d.ts';
 3 | import type {PositiveInfinity} from '../../source/numeric.d.ts';
 4 | 
 5 | expectType<TupleMax<[1, 2, 5, 3, 7, -9, -5, 0]>>(7);
 6 | expectType<TupleMax<[1, 2, 5, 3, 7, -9, -5, 0, PositiveInfinity]>>(null! as PositiveInfinity);
 7 | expectType<TupleMax<[1, 1, 1, 1, 1, 1]>>(1);
 8 | expectType<TupleMax<[-1, -2, -5]>>(-1);
 9 | expectType<TupleMax<[10, 2]>>(10);
10 | 


--------------------------------------------------------------------------------
/test-d/internal/tuple-min.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {TupleMin} from '../../source/internal/index.d.ts';
 3 | import type {NegativeInfinity, PositiveInfinity} from '../../source/numeric.d.ts';
 4 | 
 5 | declare const never: never;
 6 | 
 7 | expectType<TupleMin<[1, 2, 5, 3, 7, -9, -5, 0]>>(-9);
 8 | expectType<TupleMin<[1, 2, 5, 3, 7, -9, -5, 0, PositiveInfinity, NegativeInfinity]>>(null! as NegativeInfinity);
 9 | expectType<TupleMin<[1, 1, 1, 1, 1, 1]>>(1);
10 | expectType<TupleMin<[-1, -2, -5]>>(-5);
11 | expectType<TupleMin<[-1, -2, number, -5]>>(never);
12 | 


--------------------------------------------------------------------------------
/test-d/invariant-of.ts:
--------------------------------------------------------------------------------
 1 | import {expectAssignable, expectNotAssignable} from 'tsd';
 2 | import type {InvariantOf} from '../index.d.ts';
 3 | 
 4 | type FooBar = InvariantOf<{
 5 | 	foo: number;
 6 | 	bar: string;
 7 | }>;
 8 | 
 9 | type FooBarBaz = InvariantOf<{
10 | 	foo: number;
11 | 	bar: string;
12 | 	baz: boolean;
13 | }>;
14 | 
15 | // We make an explicit cast so we can test the value.
16 | const fooBar: FooBar = {foo: 123, bar: 'hello'} as FooBar; // eslint-disable-line @typescript-eslint/consistent-type-assertions
17 | const fooBarBaz: FooBarBaz = {foo: 123, bar: 'hello', baz: true} as FooBarBaz; // eslint-disable-line @typescript-eslint/consistent-type-assertions
18 | 
19 | // The invariantOf<Type> is assignable to Type.
20 | expectAssignable<{
21 | 	foo: number;
22 | 	bar: string;
23 | }>(fooBar);
24 | 
25 | expectNotAssignable<FooBarBaz>(fooBar); // Invariance does not accept supertypes.
26 | expectNotAssignable<FooBar>(fooBarBaz); // Invariance does not accept subtypes.
27 | 


--------------------------------------------------------------------------------
/test-d/is-any.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {IsAny} from '../index.d.ts';
 3 | 
 4 | declare const anything: any;
 5 | declare const something = 'something';
 6 | 
 7 | // `IsAny` should only be true for `any`
 8 | expectType<IsAny<any>>(true);
 9 | expectType<IsAny<typeof anything>>(true);
10 | expectType<IsAny<string>>(false);
11 | expectType<IsAny<typeof something>>(false);
12 | expectType<IsAny<never>>(false);
13 | expectType<IsAny<unknown>>(false);
14 | expectType<IsAny<null>>(false);
15 | expectType<IsAny<undefined>>(false);
16 | expectType<IsAny<void>>(false);
17 | 
18 | // Missing generic parameter
19 | // @ts-expect-error
20 | type A = IsAny;
21 | 
22 | // Verify that are no circular reference issues
23 | // https://github.com/sindresorhus/type-fest/issues/846
24 | type OnlyAny<T extends IsAny<T> extends true ? any : never> = T;
25 | type B = OnlyAny<any>;
26 | // @ts-expect-error
27 | type C = OnlyAny<string>;
28 | 


--------------------------------------------------------------------------------
/test-d/is-equal.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {IsEqual} from '../index.d.ts';
 3 | 
 4 | const notEqualNumberAndString: IsEqual<number, string> = false;
 5 | expectType<false>(notEqualNumberAndString);
 6 | 
 7 | const equalNumbers: IsEqual<1, 1> = true;
 8 | expectType<true>(equalNumbers);
 9 | 
10 | const notEqualAnyAndNumber: IsEqual<any, number> = false;
11 | expectType<false>(notEqualAnyAndNumber);
12 | 
13 | const notEqualUnionAndNumber: IsEqual<1 | 2, 1> = false;
14 | expectType<false>(notEqualUnionAndNumber);
15 | 
16 | const notEqualAnyAndNever: IsEqual<any, never> = false;
17 | expectType<false>(notEqualAnyAndNever);
18 | 
19 | const notEqualArrayOfAnyAndArrayOfNever: IsEqual<[any], [never]> = false;
20 | expectType<false>(notEqualArrayOfAnyAndArrayOfNever);
21 | 
22 | // Missing all generic parameters.
23 | // @ts-expect-error
24 | type A = IsEqual;
25 | 
26 | // Missing `Y` generic parameter.
27 | // @ts-expect-error
28 | type B = IsEqual<number>;
29 | 
30 | // Test for issue https://github.com/sindresorhus/type-fest/issues/537
31 | type UnionType = IsEqual<{a: 1} & {a: 1}, {a: 1}>; // eslint-disable-line @typescript-eslint/no-duplicate-type-constituents
32 | expectType<UnionType>(true);
33 | 
34 | type IntersectionType = IsEqual<{a: 1} | {a: 1}, {a: 1}>; // eslint-disable-line @typescript-eslint/no-duplicate-type-constituents
35 | expectType<IntersectionType>(true);
36 | 


--------------------------------------------------------------------------------
/test-d/is-float.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {IsFloat, PositiveInfinity} from '../index.d.ts';
 3 | 
 4 | declare const x: unknown;
 5 | 
 6 | expectType<true>(x as IsFloat<1.5>);
 7 | expectType<true>(x as IsFloat<999_999_999_999_999.9>);
 8 | expectType<true>(x as IsFloat<0.000_000_1>);
 9 | expectType<true>(x as IsFloat<-1e-7>);
10 | 
11 | expectType<false>(x as IsFloat<0>);
12 | expectType<false>(x as IsFloat<1>);
13 | expectType<false>(x as IsFloat<1.0>); // eslint-disable-line unicorn/no-zero-fractions
14 | expectType<false>(x as IsFloat<-1>);
15 | expectType<false>(x as IsFloat<number>);
16 | expectType<false>(x as IsFloat<0o10>);
17 | expectType<false>(x as IsFloat<1n>);
18 | expectType<false>(x as IsFloat<0n>);
19 | expectType<false>(x as IsFloat<0b10>);
20 | expectType<false>(x as IsFloat<0x10>);
21 | expectType<false>(x as IsFloat<1e+100>);
22 | expectType<false>(x as IsFloat<1.23e+21>);
23 | expectType<false>(x as IsFloat<-1.23e+21>);
24 | expectType<false>(x as IsFloat<'1.23'>);
25 | expectType<false>(x as IsFloat<PositiveInfinity>);
26 | 


--------------------------------------------------------------------------------
/test-d/is-integer.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {IsInteger, PositiveInfinity} from '../index.d.ts';
 3 | 
 4 | declare const x: unknown;
 5 | 
 6 | expectType<true>(x as IsInteger<0>);
 7 | expectType<true>(x as IsInteger<1>);
 8 | expectType<true>(x as IsInteger<1.0>); // eslint-disable-line unicorn/no-zero-fractions
 9 | expectType<true>(x as IsInteger<-1>);
10 | expectType<true>(x as IsInteger<0o10>);
11 | expectType<true>(x as IsInteger<1n>);
12 | expectType<true>(x as IsInteger<0n>);
13 | expectType<true>(x as IsInteger<0b10>);
14 | expectType<true>(x as IsInteger<0x10>);
15 | expectType<true>(x as IsInteger<1e+100>);
16 | expectType<true>(x as IsInteger<1.23e+21>);
17 | expectType<true>(x as IsInteger<-1.23e+21>);
18 | 
19 | expectType<false>(x as IsInteger<1.5>);
20 | expectType<false>(x as IsInteger<-1.5>);
21 | expectType<false>(x as IsInteger<number>);
22 | expectType<false>(x as IsInteger<PositiveInfinity>);
23 | expectType<false>(x as IsInteger<0.000_000_1>);
24 | expectType<false>(x as IsInteger<-1e-7>);
25 | 


--------------------------------------------------------------------------------
/test-d/is-never.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {IsNever} from '../index.d.ts';
 3 | 
 4 | declare const _never: never;
 5 | declare const something = 'something';
 6 | 
 7 | // `IsNever` should only be true for `any`
 8 | expectType<IsNever<never>>(true);
 9 | expectType<IsNever<typeof _never>>(true);
10 | expectType<IsNever<string>>(false);
11 | expectType<IsNever<typeof something>>(false);
12 | expectType<IsNever<any>>(false);
13 | expectType<IsNever<unknown>>(false);
14 | expectType<IsNever<null>>(false);
15 | expectType<IsNever<undefined>>(false);
16 | expectType<IsNever<void>>(false);
17 | 
18 | // Missing generic parameter
19 | // @ts-expect-error
20 | type A = IsNever;
21 | 


--------------------------------------------------------------------------------
/test-d/is-null.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {IsNull} from '../source/is-null.d.ts';
 3 | 
 4 | // https://www.typescriptlang.org/docs/handbook/type-compatibility.html
 5 | expectType<IsNull<null>>(true);
 6 | expectType<IsNull<any>>(true);
 7 | expectType<IsNull<never>>(true);
 8 | expectType<IsNull<undefined>>(false); // Depends on `strictNullChecks`
 9 | expectType<IsNull<unknown>>(false);
10 | expectType<IsNull<void>>(false);
11 | expectType<IsNull<{}>>(false);
12 | 


--------------------------------------------------------------------------------
/test-d/is-nullable.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {IsNullable} from '../source/is-nullable.d.ts';
 3 | 
 4 | expectType<IsNullable<any>>(true);
 5 | expectType<IsNullable<null>>(true);
 6 | expectType<IsNullable<null | undefined>>(true);
 7 | expectType<IsNullable<string | null>>(true);
 8 | expectType<IsNullable<string | null | undefined>>(true);
 9 | 
10 | expectType<IsNullable<string>>(false);
11 | expectType<IsNullable<string | undefined>>(false);
12 | 
13 | expectType<IsNullable<void>>(false);
14 | expectType<IsNullable<undefined>>(false);
15 | expectType<IsNullable<never>>(false);
16 | expectType<IsNullable<unknown>>(false);
17 | expectType<IsNullable<() => void>>(false);
18 | expectType<IsNullable<string & null>>(false);
19 | 


--------------------------------------------------------------------------------
/test-d/is-optional.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {IsOptional} from '../source/is-optional.d.ts';
 3 | 
 4 | expectType<IsOptional<any>>(true);
 5 | expectType<IsOptional<undefined>>(true);
 6 | expectType<IsOptional<null | undefined>>(true);
 7 | expectType<IsOptional<string | undefined>>(true);
 8 | expectType<IsOptional<string | null | undefined>>(true);
 9 | 
10 | expectType<IsOptional<string>>(false);
11 | expectType<IsOptional<string | null>>(false);
12 | 
13 | expectType<IsOptional<void>>(false);
14 | expectType<IsOptional<null>>(false);
15 | expectType<IsOptional<never>>(false);
16 | expectType<IsOptional<unknown>>(false);
17 | expectType<IsOptional<() => void>>(false);
18 | expectType<IsOptional<string & undefined>>(false);
19 | 


--------------------------------------------------------------------------------
/test-d/is-union.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {IsUnion} from '../index.d.ts';
 3 | 
 4 | expectType<IsUnion<1>>(false);
 5 | expectType<IsUnion<true>>(false);
 6 | expectType<IsUnion<'foo'>>(false);
 7 | expectType<IsUnion<[]>>(false);
 8 | expectType<IsUnion<{}>>(false);
 9 | expectType<IsUnion<1 & {}>>(false);
10 | expectType<IsUnion<never>>(false);
11 | expectType<IsUnion<unknown>>(false);
12 | expectType<IsUnion<any>>(false);
13 | 
14 | expectType<IsUnion<1 | 2>>(true);
15 | expectType<IsUnion<'foo' | 'bar'>>(true);
16 | expectType<IsUnion<'foo' | 'bar' | 1>>(true);
17 | expectType<IsUnion<'foo' | 1>>(true);
18 | expectType<IsUnion<[] | {}>>(true);
19 | 


--------------------------------------------------------------------------------
/test-d/is-unknown.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {IsUnknown} from '../index.d.ts';
 3 | 
 4 | declare const _unknown: unknown;
 5 | declare const something = 'something';
 6 | 
 7 | // `IsUnknown` should only be true for `any`
 8 | expectType<IsUnknown<unknown>>(true);
 9 | expectType<IsUnknown<typeof _unknown>>(true);
10 | expectType<IsUnknown<string>>(false);
11 | expectType<IsUnknown<typeof something>>(false);
12 | expectType<IsUnknown<any>>(false);
13 | expectType<IsUnknown<never>>(false);
14 | expectType<IsUnknown<null>>(false);
15 | expectType<IsUnknown<undefined>>(false);
16 | expectType<IsUnknown<void>>(false);
17 | 
18 | // Missing generic parameter
19 | // @ts-expect-error
20 | type A = IsUnknown;
21 | 


--------------------------------------------------------------------------------
/test-d/iterable-element.ts:
--------------------------------------------------------------------------------
 1 | import {expectAssignable, expectType} from 'tsd';
 2 | import type {IterableElement} from '../index.d.ts';
 3 | 
 4 | declare const iterableElement: IterableElement<ReturnType<typeof secretGenerator>>;
 5 | expectType<1 | 'two'>(iterableElement);
 6 | 
 7 | declare const iterableElementAsync: IterableElement<ReturnType<typeof secretGeneratorAsync>>;
 8 | expectType<true | Date>(iterableElementAsync);
 9 | 
10 | function * secretGenerator() {
11 | 	yield 1;
12 | 	yield 'two';
13 | }
14 | 
15 | async function * secretGeneratorAsync() {
16 | 	yield true;
17 | 	yield new Date();
18 | }
19 | 
20 | const fruits = new Set(['🍎', '🍌', '🍉'] as const);
21 | 
22 | type Fruit = IterableElement<typeof fruits>;
23 | 
24 | expectAssignable<Fruit>('🍎');
25 | expectAssignable<Fruit>('🍌');
26 | expectAssignable<Fruit>('🍉');
27 | 
28 | type VegetableSet = Set<'🥦' | '🥕' | '🌶'>;
29 | type Vegetable = IterableElement<VegetableSet>;
30 | 
31 | expectAssignable<Vegetable>('🥦');
32 | expectAssignable<Vegetable>('🥕');
33 | expectAssignable<Vegetable>('🌶');
34 | 
35 | type UserRolesSet = ReadonlySet<'regular' | 'contributor' | 'maintainer'>;
36 | type UserRole = IterableElement<UserRolesSet>;
37 | 
38 | expectAssignable<UserRole>('regular');
39 | expectAssignable<UserRole>('contributor');
40 | expectAssignable<UserRole>('maintainer');
41 | 


--------------------------------------------------------------------------------
/test-d/jsonifiable.ts:
--------------------------------------------------------------------------------
 1 | import {expectAssignable, expectNotAssignable} from 'tsd';
 2 | import type {Jsonifiable} from '../index.d.ts';
 3 | 
 4 | expectAssignable<Jsonifiable>(1);
 5 | expectAssignable<Jsonifiable>('');
 6 | expectAssignable<Jsonifiable>(null);
 7 | expectAssignable<Jsonifiable>(new Date());
 8 | expectAssignable<Jsonifiable>({a: new Date()});
 9 | expectAssignable<Jsonifiable>([new Date()]);
10 | expectAssignable<Jsonifiable>({a: undefined});
11 | expectAssignable<Jsonifiable>([1, 2, 3] as const);
12 | expectAssignable<Jsonifiable>({a: new Date()} as const);
13 | expectAssignable<Jsonifiable>({a: {deeply: {nested: {toJsonObject: new Date()}}}});
14 | expectAssignable<Jsonifiable>({toJSON: () => new Date()});
15 | expectAssignable<Jsonifiable>({
16 | 	toJSON() {
17 | 		return {
18 | 			foo: {
19 | 				toJSON() {
20 | 					return {bar: 'bar'};
21 | 				},
22 | 			},
23 | 		};
24 | 	},
25 | });
26 | 
27 | expectNotAssignable<Jsonifiable>(undefined);
28 | expectNotAssignable<Jsonifiable>(new Map());
29 | expectNotAssignable<Jsonifiable>({a: new Map()});
30 | expectNotAssignable<Jsonifiable>([new Map()]);
31 | 


--------------------------------------------------------------------------------
/test-d/kebab-cased-properties-deep.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {KebabCasedPropertiesDeep} from '../index.d.ts';
 3 | 
 4 | type FooBar = {helloWorld: {p2p: Array<{addressLine1: string}>}};
 5 | 
 6 | declare const foo: KebabCasedPropertiesDeep<FooBar>;
 7 | expectType<{'hello-world': {p2p: Array<{'address-line1': string}>}}>(foo);
 8 | 
 9 | declare const bar: KebabCasedPropertiesDeep<FooBar, {splitOnNumbers: true}>;
10 | expectType<{'hello-world': {'p-2-p': Array<{'address-line-1': string}>}}>(bar);
11 | 
12 | // Verify example
13 | type User = {
14 | 	userId: number;
15 | 	userName: string;
16 | 	date: Date;
17 | 	regExp: RegExp;
18 | };
19 | 
20 | type UserWithFriends = {
21 | 	userInfo: User;
22 | 	userFriends: User[];
23 | };
24 | 
25 | const result: KebabCasedPropertiesDeep<UserWithFriends> = {
26 | 	'user-info': {
27 | 		'user-id': 1,
28 | 		'user-name': 'Tom',
29 | 		date: new Date(),
30 | 		'reg-exp': /.*/,
31 | 	},
32 | 	'user-friends': [
33 | 		{
34 | 			'user-id': 2,
35 | 			'user-name': 'Jerry',
36 | 			date: new Date(),
37 | 			'reg-exp': /.*/,
38 | 		},
39 | 		{
40 | 			'user-id': 3,
41 | 			'user-name': 'Spike',
42 | 			date: new Date(),
43 | 			'reg-exp': /.*/,
44 | 		},
45 | 	],
46 | };
47 | expectType<KebabCasedPropertiesDeep<UserWithFriends>>(result);
48 | 
49 | expectType<{'foo-bar': unknown}>({} as KebabCasedPropertiesDeep<{foo_bar: unknown}>);
50 | expectType<{'foo-bar': {'bar-baz': unknown}; biz: unknown}>({} as KebabCasedPropertiesDeep<{foo_bar: {bar_baz: unknown}; biz: unknown}>);
51 | 
52 | expectType<{'foo-bar': any}>({} as KebabCasedPropertiesDeep<{foo_bar: any}>);
53 | expectType<{'foo-bar': {'bar-baz': any}; biz: any}>({} as KebabCasedPropertiesDeep<{foo_bar: {bar_baz: any}; biz: any}>);
54 | 


--------------------------------------------------------------------------------
/test-d/kebab-cased-properties.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {KebabCasedProperties} from '../index.d.ts';
 3 | 
 4 | type Foobar = {helloWorld1: {fooBar: string}};
 5 | 
 6 | declare const foo: KebabCasedProperties<Foobar>;
 7 | expectType<{'hello-world1': {fooBar: string}}>(foo);
 8 | 
 9 | declare const bar: KebabCasedProperties<Foobar, {splitOnNumbers: true}>;
10 | expectType<{'hello-world-1': {fooBar: string}}>(bar);
11 | 
12 | // Verify example
13 | type User = {
14 | 	userId: number;
15 | 	userName: string;
16 | };
17 | const result: KebabCasedProperties<User> = {
18 | 	'user-id': 1,
19 | 	'user-name': 'Tom',
20 | };
21 | expectType<KebabCasedProperties<User>>(result);
22 | 


--------------------------------------------------------------------------------
/test-d/key-as-string.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {KeyAsString} from '../source/key-as-string.d.ts';
 3 | 
 4 | declare const foo: KeyAsString<{
 5 | 	1: number;
 6 | 	stringKey: string;
 7 | }>;
 8 | 
 9 | expectType<'1' | 'stringKey'>(foo);
10 | 
11 | declare const sym: unique symbol;
12 | expectType<'1' | 'foo'>({} as KeyAsString<{[sym]: unknown; 1: number; foo: string}>); // Ignores symbol keys
13 | 
14 | // Index signatures
15 | expectType<string>({} as KeyAsString<{[x: string]: unknown}>);
16 | expectType<`${number}`>({} as KeyAsString<{[x: number]: unknown}>);
17 | expectType<`foo${string}` | `${number}`>({} as KeyAsString<{[x: `foo${string}`]: unknown; [y: number]: unknown}>);
18 | expectType<string>({} as KeyAsString<{[x: string]: unknown; [y: symbol]: unknown}>);
19 | expectType<never>({} as KeyAsString<{[x: symbol]: unknown}>);
20 | 
21 | // Unions
22 | expectType<'1'>({} as KeyAsString<{1: number; foo: string} | {1: number; bar: string}>); // Only grabs the common keys, just like `keyof`.
23 | expectType<never>({} as KeyAsString<{foo: string} | {bar: string}>);
24 | 
25 | // Boundary cases
26 | expectType<string>({} as KeyAsString<any>);
27 | expectType<string>({} as KeyAsString<never>);
28 | 


--------------------------------------------------------------------------------
/test-d/last-array-element.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {LastArrayElement} from '../index.d.ts';
 3 | 
 4 | declare function lastOf<V extends readonly unknown[]>(array: V): LastArrayElement<V>;
 5 | const array: ['foo', 2, 'bar'] = ['foo', 2, 'bar'];
 6 | const mixedArray: ['bar', 'foo', 2] = ['bar', 'foo', 2];
 7 | 
 8 | expectType<'bar'>(lastOf(array));
 9 | expectType<2>(lastOf(mixedArray));
10 | expectType<string>(lastOf(['a', 'b', 'c']));
11 | expectType<string | number>(lastOf(['a', 'b', 1]));
12 | expectType<1>(lastOf(['a', 'b', 1] as const));
13 | 
14 | declare const leadingSpreadTuple: [...string[], object, number];
15 | expectType<number>(lastOf(leadingSpreadTuple));
16 | 
17 | declare const trailingSpreadTuple1: [string, ...number[]];
18 | expectType<number | string>(lastOf(trailingSpreadTuple1));
19 | 
20 | declare const trailingSpreadTuple2: [string, boolean, ...number[]];
21 | expectType<number | boolean>(lastOf(trailingSpreadTuple2));
22 | 
23 | // eslint-disable-next-line @typescript-eslint/array-type
24 | declare const trailingSpreadTuple3: ['foo', true, ...(1 | '2')[]];
25 | expectType<true | 1 | '2'>(lastOf(trailingSpreadTuple3));
26 | 


--------------------------------------------------------------------------------
/test-d/less-than-or-equal.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {LessThanOrEqual} from '../index.d.ts';
 3 | import type {NegativeInfinity, PositiveInfinity} from '../source/numeric.d.ts';
 4 | 
 5 | declare const never: never;
 6 | 
 7 | expectType<LessThanOrEqual<1, 2>>(true);
 8 | expectType<LessThanOrEqual<2, 1>>(false);
 9 | expectType<LessThanOrEqual<10, 2>>(false);
10 | expectType<LessThanOrEqual<10, -2>>(false);
11 | expectType<LessThanOrEqual<2, 2>>(true);
12 | expectType<LessThanOrEqual<-2, -2>>(true);
13 | expectType<LessThanOrEqual<-2, -3>>(false);
14 | expectType<LessThanOrEqual<-2, number>>(never);
15 | expectType<LessThanOrEqual<PositiveInfinity, -999>>(false);
16 | expectType<LessThanOrEqual<PositiveInfinity, 999>>(false);
17 | expectType<LessThanOrEqual<999, PositiveInfinity>>(true);
18 | expectType<LessThanOrEqual<999, NegativeInfinity>>(false);
19 | expectType<LessThanOrEqual<-999, NegativeInfinity>>(false);
20 | expectType<LessThanOrEqual<PositiveInfinity, PositiveInfinity>>(true);
21 | expectType<LessThanOrEqual<NegativeInfinity, NegativeInfinity>>(true);
22 | expectType<LessThanOrEqual<PositiveInfinity, NegativeInfinity>>(false);
23 | 


--------------------------------------------------------------------------------
/test-d/less-than.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {LessThan} from '../index.d.ts';
 3 | import type {NegativeInfinity, PositiveInfinity} from '../source/numeric.d.ts';
 4 | 
 5 | declare const never: never;
 6 | 
 7 | expectType<LessThan<1, 2>>(true);
 8 | expectType<LessThan<2, 1>>(false);
 9 | expectType<LessThan<10, 2>>(false);
10 | expectType<LessThan<10, -2>>(false);
11 | expectType<LessThan<2, 2>>(false);
12 | expectType<LessThan<-2, -2>>(false);
13 | expectType<LessThan<-2, -3>>(false);
14 | expectType<LessThan<-2, number>>(never);
15 | 
16 | // === unions ===
17 | expectType<LessThan<10, 50 | 100>>(true);
18 | expectType<LessThan<50 | 25 | 0 | -16, 100>>(true);
19 | expectType<LessThan<1 | 2, 3 | 4>>(true);
20 | 
21 | expectType<LessThan<100 | 200, 50>>(false);
22 | expectType<LessThan<25, -100 | -15 | 2 | 21>>(false);
23 | expectType<LessThan<10 | 15, -5 | 10>>(false);
24 | 
25 | expectType<LessThan<-10, -90 | 90>>({} as boolean);
26 | expectType<LessThan<-16 | 16, 0>>({} as boolean);
27 | expectType<LessThan<-4 | 45, 20 | 30>>({} as boolean);
28 | expectType<LessThan<1 | -1 | 3, 0 | 2>>({} as boolean);
29 | 
30 | expectType<LessThan<PositiveInfinity, -999>>(false);
31 | expectType<LessThan<PositiveInfinity, 999>>(false);
32 | expectType<LessThan<999, PositiveInfinity>>(true);
33 | expectType<LessThan<999, NegativeInfinity>>(false);
34 | expectType<LessThan<-999, NegativeInfinity>>(false);
35 | expectType<LessThan<PositiveInfinity, PositiveInfinity>>(false);
36 | expectType<LessThan<NegativeInfinity, NegativeInfinity>>(false);
37 | expectType<LessThan<PositiveInfinity, NegativeInfinity>>(false);
38 | 


--------------------------------------------------------------------------------
/test-d/literal-to-primitive-deep.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {IsEqual, LiteralToPrimitiveDeep} from '../index.d.ts';
 3 | 
 4 | type LiteralObject = {
 5 | 	a: string;
 6 | 	b: number;
 7 | 	c: boolean;
 8 | 	d: {
 9 | 		e: bigint;
10 | 		f: symbol;
11 | 		g: {
12 | 			h: string[];
13 | 			i: {
14 | 				j: boolean;
15 | 				k: {
16 | 					l: 1;
17 | 					m: 'hello';
18 | 					o: [1, 2, 3];
19 | 					p: ['a', 'b', 'c'];
20 | 					q: [1, 'a', true];
21 | 				};
22 | 			};
23 | 		};
24 | 	};
25 | };
26 | 
27 | type PrimitiveObject = {
28 | 	a: string;
29 | 	b: number;
30 | 	c: boolean;
31 | 	d: {
32 | 		e: bigint;
33 | 		f: symbol;
34 | 		g: {
35 | 			h: string[];
36 | 			i: {
37 | 				j: boolean;
38 | 				k: {
39 | 					l: number;
40 | 					m: string;
41 | 					o: number[];
42 | 					p: string[];
43 | 					q: Array<number | string | boolean>;
44 | 				};
45 | 			};
46 | 		};
47 | 	};
48 | };
49 | 
50 | const typeEqual: IsEqual<
51 | 	LiteralToPrimitiveDeep<LiteralObject>,
52 | 	PrimitiveObject
53 | > = true;
54 | expectType<true>(typeEqual);
55 | 


--------------------------------------------------------------------------------
/test-d/literal-to-primitive.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {LiteralToPrimitive} from '../index.d.ts';
 3 | 
 4 | // Simple usage
 5 | declare const numberPrimitive: LiteralToPrimitive<123>;
 6 | expectType<number>(numberPrimitive);
 7 | 
 8 | const symbol = Symbol('foo');
 9 | 
10 | // Union
11 | declare const kitchenSink: LiteralToPrimitive<123 | 123n | 'hello' | true | undefined | typeof symbol | null | {key: string}>;
12 | expectType<number | bigint | string | boolean | undefined | symbol | null>(kitchenSink);
13 | 


--------------------------------------------------------------------------------
/test-d/merge-exclusive.ts:
--------------------------------------------------------------------------------
 1 | import {expectNotAssignable, expectAssignable} from 'tsd';
 2 | import type {MergeExclusive} from '../index.d.ts';
 3 | 
 4 | type BaseOptions = {
 5 | 	option?: string;
 6 | };
 7 | 
 8 | type ExclusiveVariation1 = {
 9 | 	exclusive1: boolean;
10 | } & BaseOptions;
11 | 
12 | type ExclusiveVariation2 = {
13 | 	exclusive2: number;
14 | } & BaseOptions;
15 | 
16 | type Options = MergeExclusive<ExclusiveVariation1, ExclusiveVariation2>;
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 | expectNotAssignable<Options>({exclusive1: true, exclusive2: 1});
29 | 


--------------------------------------------------------------------------------
/test-d/multidimensional-array.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {MultidimensionalArray} from '../index.d.ts';
 3 | 
 4 | function createArray<T extends number>(dimensions: T): MultidimensionalArray<unknown, T> {
 5 | 	const root: unknown[] = [];
 6 | 
 7 | 	let array = root;
 8 | 	for (let dimension = 1; dimension < dimensions; ++dimension) {
 9 | 		array[0] = [];
10 | 		array = array[0] as unknown[];
11 | 	}
12 | 
13 | 	return root as MultidimensionalArray<unknown, T>;
14 | }
15 | 
16 | const a: MultidimensionalArray<number, 3> = [];
17 | const b: MultidimensionalArray<boolean, number> = [];
18 | const c = createArray(2);
19 | const d = createArray(7);
20 | 
21 | // @ts-expect-error
22 | a[0][0][0] = 42;
23 | 
24 | type RecursiveArray<T> = Array<RecursiveArray<T>>;
25 | 
26 | expectType<number[][][]>(a);
27 | expectType<RecursiveArray<boolean>>(b);
28 | expectType<unknown[][]>(c);
29 | expectType<unknown[][][][][][][]>(d);
30 | 


--------------------------------------------------------------------------------
/test-d/multidimensional-readonly-array.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {MultidimensionalReadonlyArray} from '../index.d.ts';
 3 | 
 4 | function createArray<T extends number>(dimensions: T): MultidimensionalReadonlyArray<string, T> {
 5 | 	const root: unknown[] = [];
 6 | 
 7 | 	let array = root;
 8 | 	for (let dimension = 1; dimension < dimensions; ++dimension) {
 9 | 		array[0] = [];
10 | 		if (dimension < dimensions - 1) {
11 | 			array = array[0] as unknown[];
12 | 		} else {
13 | 			array[0] = '42';
14 | 		}
15 | 	}
16 | 
17 | 	return root as MultidimensionalReadonlyArray<unknown, T> as MultidimensionalReadonlyArray<string, T>;
18 | }
19 | 
20 | const a: MultidimensionalReadonlyArray<number, 3> = [];
21 | const b: MultidimensionalReadonlyArray<boolean, number> = [];
22 | const c = createArray(2);
23 | 
24 | const answer = c?.[0]?.[0]; // '42'
25 | 
26 | type RecursiveArray<T> = ReadonlyArray<RecursiveArray<T>>;
27 | 
28 | expectType<string | undefined>(answer);
29 | 
30 | expectType<ReadonlyArray<ReadonlyArray<readonly number[]>>>(a);
31 | expectType<RecursiveArray<boolean>>(b);
32 | expectType<ReadonlyArray<readonly string[]>>(c);
33 | 


--------------------------------------------------------------------------------
/test-d/non-empty-object.ts:
--------------------------------------------------------------------------------
 1 | import {expectNever, expectType} from 'tsd';
 2 | import type {NonEmptyObject, RequireAtLeastOne} from '../index.d.ts';
 3 | 
 4 | type TestType1 = {
 5 | 	a: string;
 6 | 	b: boolean;
 7 | };
 8 | 
 9 | type TestType2 = {
10 | 	a?: string;
11 | 	b?: boolean;
12 | };
13 | 
14 | type TestType3 = {
15 | 	a: string;
16 | 	b?: boolean;
17 | };
18 | 
19 | type TestType4 = {};
20 | 
21 | declare const test1: NonEmptyObject<TestType1>;
22 | declare const test2: NonEmptyObject<TestType2>;
23 | declare const test3: NonEmptyObject<TestType3>;
24 | declare const test4: NonEmptyObject<TestType4>;
25 | 
26 | expectType<TestType1>(test1);
27 | expectType<RequireAtLeastOne<TestType2>>(test2);
28 | expectType<TestType3>(test3);
29 | expectNever(test4);
30 | 


--------------------------------------------------------------------------------
/test-d/non-empty-string.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {NonEmptyString} from '../index.d.ts';
 3 | 
 4 | expectType<never>({} as NonEmptyString<''>);
 5 | 
 6 | expectType<'a'>({} as NonEmptyString<'a'>);
 7 | 
 8 | expectType<never>({} as NonEmptyString<string>);
 9 | expectType<never>({} as NonEmptyString<Uppercase<string>>);
10 | expectType<`on${string}`>({} as NonEmptyString<`on${string}`>);
11 | 
12 | expectType<'a' | 'b'>({} as NonEmptyString<'a' | 'b'>);
13 | expectType<'a' | `${number}.${number}`>({} as NonEmptyString<'a' | `${number}.${number}`>);
14 | expectType<never>({} as NonEmptyString<'' | 'a'>);
15 | expectType<never>({} as NonEmptyString<'a' | Uppercase<string>>);
16 | expectType<never>({} as NonEmptyString<'' | `on${string}`>);
17 | 
18 | // `NonEmptyString<S>` should be assignable to `string`
19 | type Assignability1<_S extends string> = unknown;
20 | type Test1<S extends string> = Assignability1<NonEmptyString<S>>;
21 | 
22 | // `string` should NOT be assignable to `NonEmptyString<S>`
23 | type Assignability2<_S extends string, _SS extends NonEmptyString<_S>> = unknown;
24 | // @ts-expect-error
25 | type Test2<S extends string> = Assignability2<S, S>;
26 | 


--------------------------------------------------------------------------------
/test-d/non-empty-tuple.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {NonEmptyTuple} from '../index.d.ts';
 3 | 
 4 | declare const sum: (...numbers: NonEmptyTuple<number>) => number;
 5 | 
 6 | expectType<number>(sum(1, 2, 3));
 7 | expectType<number>(sum(1));
 8 | 
 9 | // @ts-expect-error
10 | sum();
11 | 


--------------------------------------------------------------------------------
/test-d/observable-like.ts:
--------------------------------------------------------------------------------
 1 | import {expectType, expectAssignable} from 'tsd';
 2 | import type {ObservableLike} from '../source/globals/index.d.ts';
 3 | 
 4 | // eslint-disable-next-line no-use-extend-native/no-use-extend-native
 5 | expectAssignable<symbol>(Symbol.observable);
 6 | 
 7 | const observable = (null as any) as ObservableLike;
 8 | 
 9 | const subscription = observable.subscribe({
10 | 	next() {}, // eslint-disable-line @typescript-eslint/no-empty-function
11 | });
12 | expectType<{unsubscribe(): void}>(subscription);
13 | 
14 | observable.subscribe({
15 | 	next(value) {
16 | 		expectType<unknown>(value);
17 | 	},
18 | });
19 | 
20 | const observable2 = (null as any) as ObservableLike<string>;
21 | 
22 | observable2.subscribe({
23 | 	next() {}, // eslint-disable-line @typescript-eslint/no-empty-function
24 | });
25 | observable2.subscribe({
26 | 	next(value) {
27 | 		expectType<string>(value);
28 | 	},
29 | });
30 | 


--------------------------------------------------------------------------------
/test-d/omit-index-signature.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {OmitIndexSignature} from '../index.d.ts';
 3 | 
 4 | type ExampleInterface = {
 5 | 	// These index signatures will be removed.
 6 | 	[x: string]: any;
 7 | 	[x: number]: any;
 8 | 	[x: symbol]: any;
 9 | 	[x: `head-${string}`]: string;
10 | 	[x: `${string}-tail`]: string;
11 | 	[x: `head-${string}-tail`]: string;
12 | 	[x: `${bigint}`]: string;
13 | 	[x: `embedded-${number}`]: string;
14 | 
15 | 	// These explicitly defined keys will remain.
16 | 	foo: 'bar';
17 | 	qux?: 'baz';
18 | };
19 | 
20 | type MappedType<ObjectType> = {
21 | 	[Key in keyof ObjectType]: {
22 | 		key: Key;
23 | 		value: Exclude<ObjectType[Key], undefined>;
24 | 	};
25 | };
26 | 
27 | declare const exampleInterfaceKnownKeys: OmitIndexSignature<ExampleInterface>;
28 | expectType<{
29 | 	foo: 'bar';
30 | 	qux?: 'baz';
31 | }>(exampleInterfaceKnownKeys);
32 | 
33 | declare const exampleMappedTypeKnownKeys: OmitIndexSignature<
34 | 	MappedType<ExampleInterface>
35 | >;
36 | expectType<{
37 | 	foo: {key: 'foo'; value: 'bar'};
38 | 	qux?: {key: 'qux'; value: 'baz'};
39 | }>(exampleMappedTypeKnownKeys);
40 | 


--------------------------------------------------------------------------------
/test-d/or.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {Or} from '../source/or.d.ts';
 3 | 
 4 | expectType<Or<true, true>>(true);
 5 | expectType<Or<true, false>>(true);
 6 | expectType<Or<false, true>>(true);
 7 | expectType<Or<false, false>>(false);
 8 | 
 9 | expectType<Or<true, boolean>>(true);
10 | expectType<Or<boolean, true>>(true);
11 | expectType<Or<false, boolean>>({} as boolean);
12 | expectType<Or<boolean, false>>({} as boolean);
13 | expectType<Or<boolean, boolean>>({} as boolean);
14 | 
15 | expectType<Or<true, any>>(true);
16 | expectType<Or<any, true>>(true);
17 | expectType<Or<false, any>>({} as boolean);
18 | expectType<Or<any, false>>({} as boolean);
19 | expectType<Or<boolean, any>>({} as boolean);
20 | expectType<Or<any, boolean>>({} as boolean);
21 | expectType<Or<any, any>>({} as boolean);
22 | 
23 | expectType<Or<true, never>>(true);
24 | expectType<Or<never, true>>(true);
25 | expectType<Or<false, never>>(false);
26 | expectType<Or<never, false>>(false);
27 | expectType<Or<boolean, never>>({} as boolean);
28 | expectType<Or<never, boolean>>({} as boolean);
29 | expectType<Or<never, never>>(false);
30 | 


--------------------------------------------------------------------------------
/test-d/override-properties.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import {expectTypeOf} from 'expect-type';
 3 | import type {OverrideProperties} from '../source/override-properties.d.ts';
 4 | 
 5 | type Foo = {
 6 | 	a: number;
 7 | 	b: string;
 8 | };
 9 | 
10 | const fixture: OverrideProperties<Foo, {b: number}> = {a: 1, b: 2};
11 | expectType<{a: number; b: number}>(fixture);
12 | 
13 | // @ts-expect-error
14 | type Bar = OverrideProperties<Foo, {c: number}>;
15 | 
16 | // @ts-expect-error
17 | type Bar = OverrideProperties<Foo, {b: number; c: number}>;
18 | 
19 | // Test for https://github.com/sindresorhus/type-fest/issues/858
20 | { // eslint-disable-line no-lone-blocks
21 | 	type Original = {
22 | 		foo: string;
23 | 		bar: string;
24 | 	};
25 | 
26 | 	type Modified = {
27 | 		foo: string | undefined;
28 | 		bar: string;
29 | 	};
30 | 
31 | 	type Final = OverrideProperties<Original, Modified>;
32 | 
33 | 	expectTypeOf<Final>().toMatchTypeOf<{foo: string | undefined; bar: string}>();
34 | }
35 | 


--------------------------------------------------------------------------------
/test-d/pascal-case.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {PascalCase} from '../index.d.ts';
 3 | 
 4 | const pascalFromCamel: PascalCase<'fooBar'> = 'FooBar';
 5 | expectType<'FooBar'>(pascalFromCamel);
 6 | 
 7 | const pascalFromKebab: PascalCase<'foo-bar'> = 'FooBar';
 8 | expectType<'FooBar'>(pascalFromKebab);
 9 | 
10 | const pascalFromComplexKebab: PascalCase<'foo-bar-abc-123'> = 'FooBarAbc123';
11 | expectType<'FooBarAbc123'>(pascalFromComplexKebab);
12 | 
13 | expectType<PascalCase<'fooBAR'>>('FooBar');
14 | expectType<PascalCase<'fooBAR', {preserveConsecutiveUppercase: true}>>('FooBAR');
15 | 
16 | expectType<PascalCase<'fooBARBiz'>>('FooBarBiz');
17 | expectType<PascalCase<'fooBARBiz', {preserveConsecutiveUppercase: true}>>('FooBARBiz');
18 | 
19 | expectType<PascalCase<'foo BAR-Biz_BUZZ', {preserveConsecutiveUppercase: true}>>('FooBARBizBUZZ');
20 | expectType<PascalCase<'foo BAR-Biz_BUZZ', {preserveConsecutiveUppercase: false}>>('FooBarBizBuzz');
21 | expectType<PascalCase<'foo\tBAR-Biz_BUZZ'>>('FooBarBizBuzz');
22 | 
23 | expectType<PascalCase<string, {preserveConsecutiveUppercase: true}>>({} as Capitalize<string>);
24 | expectType<PascalCase<string>>({} as Capitalize<string>);
25 | 


--------------------------------------------------------------------------------
/test-d/pascal-cased-properties.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {PascalCasedProperties} from '../index.d.ts';
 3 | 
 4 | declare const foo: PascalCasedProperties<{helloWorld: {fooBar: string}}>;
 5 | expectType<{HelloWorld: {fooBar: string}}>(foo);
 6 | 
 7 | declare const bar: PascalCasedProperties<Array<{helloWorld: string}>>;
 8 | expectType<Array<{helloWorld: string}>>(bar);
 9 | 
10 | declare const fooBar: PascalCasedProperties<() => {a: string}>;
11 | expectType<() => {a: string}>(fooBar);
12 | 
13 | // Verify example
14 | type User = {
15 | 	userId: number;
16 | 	userName: string;
17 | };
18 | const result: PascalCasedProperties<User> = {
19 | 	UserId: 1,
20 | 	UserName: 'Tom',
21 | };
22 | expectType<PascalCasedProperties<User>>(result);
23 | 
24 | declare const baz: PascalCasedProperties<{fooBAR: number; BARFoo: string}, {preserveConsecutiveUppercase: true}>;
25 | expectType<{FooBAR: number; BARFoo: string}>(baz);
26 | 
27 | declare const biz: PascalCasedProperties<{fooBAR: number; BARFoo: string}>;
28 | expectType<{FooBar: number; BarFoo: string}>(biz);
29 | 


--------------------------------------------------------------------------------
/test-d/pick-index-signature.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {PickIndexSignature, Simplify} from '../index.d.ts';
 3 | 
 4 | declare const symbolKey: unique symbol;
 5 | 
 6 | type Foo = {
 7 | 	[x: string]: unknown;
 8 | 	[x: number]: unknown;
 9 | 	[x: symbol]: unknown;
10 | 	[x: `head-${string}`]: string;
11 | 	[x: `${string}-tail`]: string;
12 | 	[x: `head-${string}-tail`]: string;
13 | 	[x: `${bigint}`]: string;
14 | 	[x: `embedded-${number}`]: string;
15 | };
16 | 
17 | type Bar = {
18 | 	['kebab-case-key']: string;
19 | 	[symbolKey]: string;
20 | 	foo: 'bar';
21 | 	qux?: 'baz';
22 | };
23 | 
24 | type FooBar = Simplify<Foo & Bar>;
25 | 
26 | declare const indexSignature: PickIndexSignature<FooBar>;
27 | 
28 | expectType<Foo>(indexSignature);
29 | 


--------------------------------------------------------------------------------
/test-d/promisable.ts:
--------------------------------------------------------------------------------
1 | import {expectType} from 'tsd';
2 | import type {Promisable} from '../index.d.ts';
3 | 
4 | declare const promisable: Promisable<string>;
5 | expectType<PromiseLike<string> | string>(promisable);
6 | 


--------------------------------------------------------------------------------
/test-d/readonly-tuple.ts:
--------------------------------------------------------------------------------
 1 | import {expectAssignable, expectNotAssignable} from 'tsd';
 2 | import type {ReadonlyTuple} from '../index.d.ts';
 3 | 
 4 | type TupleOfThreeStrings = ReadonlyTuple<string, 3>;
 5 | 
 6 | expectAssignable<TupleOfThreeStrings>(['a', 'b', 'c']);
 7 | 
 8 | expectNotAssignable<TupleOfThreeStrings>(['a', 'b', 123]);
 9 | expectNotAssignable<TupleOfThreeStrings>(['a']);
10 | expectNotAssignable<TupleOfThreeStrings>(['a', 'b']);
11 | expectNotAssignable<TupleOfThreeStrings>(['a', 'b', 'c', 'd']);
12 | 
13 | declare const test: TupleOfThreeStrings;
14 | 
15 | // @ts-expect-error
16 | const _a: unknown = test.push;
17 | // @ts-expect-error
18 | test[2] = 'a';
19 | 


--------------------------------------------------------------------------------
/test-d/set-non-nullable.ts:
--------------------------------------------------------------------------------
 1 | import {expectNotAssignable, expectType} from 'tsd';
 2 | import type {SetNonNullable} from '../index.d.ts';
 3 | 
 4 | // Update one possibly undefined key and one possibly null key to non-nullable.
 5 | declare const variation1: SetNonNullable<{a: number; b: string | undefined; c: boolean | null}, 'b' | 'c'>;
 6 | expectType<{a: number; b: string; c: boolean}>(variation1);
 7 | 
 8 | // Update a key that is possibly null or undefined.
 9 | declare const variation2: SetNonNullable<{a: number; b: string | null | undefined}, 'b'>;
10 | expectType<{a: number; b: string}>(variation2);
11 | 
12 | // Update an optional key.
13 | declare const variation3: SetNonNullable<{a: number; b?: string | undefined}, 'b'>;
14 | expectType<{a: number; b?: string}>(variation3);
15 | 
16 | // Fail if type changes even if non-nullable is right.
17 | declare const variation4: SetNonNullable<{a: number; b: string | undefined}, 'b'>;
18 | expectNotAssignable<{a: string; b: string}>(variation4);
19 | 
20 | // Update all keys if `Keys` generic is not passed.
21 | declare const variation5: SetNonNullable<{a: number; b: string | undefined; c: boolean | null}>;
22 | expectType<{a: number; b: string; c: boolean}>(variation5);
23 | 
24 | // Does not throw type error in type predicate contexts.
25 | type Variation6Config = {a: boolean | null; b: boolean | null};
26 | const variant6Function = <TProperty extends keyof Variation6Config>(
27 | 	config: Variation6Config,
28 | 	property: TProperty,
29 | ): config is SetNonNullable<Variation6Config, TProperty> => Boolean(config[property]);
30 | expectNotAssignable<never>(variant6Function); // Just to prevent unused error.
31 | 


--------------------------------------------------------------------------------
/test-d/set-return-type.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {SetReturnType} from '../index.d.ts';
 3 | 
 4 | declare const anything: unknown;
 5 | 
 6 | // Without `thisArg` and without parameters.
 7 | declare const variation1: SetReturnType<() => void, number>;
 8 | expectType<() => number>(variation1);
 9 | variation1.call(anything);
10 | 
11 | // Without `thisArg` and with parameters.
12 | declare const variation2: SetReturnType<(foo: string, bar: boolean) => number, void>;
13 | expectType<(foo: string, bar: boolean) => void>(variation2);
14 | variation2.call(anything, 'foo', true);
15 | 
16 | // With `thisArg` and without parameters.
17 | function function1(this: Date): void {} // eslint-disable-line @typescript-eslint/no-empty-function
18 | declare const variation3: SetReturnType<typeof function1, string[]>;
19 | expectType<(this: Date) => string[]>(variation3);
20 | variation3.call(new Date());
21 | // @ts-expect-error
22 | variation3.call('not-a-date');
23 | 
24 | // With `thisArg` and with parameters.
25 | declare function function2(this: Date, foo: any, bar: Array<[number]>): any;
26 | declare const variation4: SetReturnType<typeof function2, never>;
27 | expectType<(this: Date, foo: any, bar: Array<[number]>) => never>(variation4);
28 | variation4.call(new Date(), anything, [[4], [7]]);
29 | // @ts-expect-error
30 | variation4.call('not-a-date', anything, [[4], [7]]);
31 | 
32 | // Sanity check to the fact that omitting `this: unknown` from the argument list has no effect other than in readability.
33 | declare function withExplicitThis(this: unknown, foo: string): number;
34 | declare function withImplicitThis(foo: string): number;
35 | expectType<typeof withExplicitThis>(withImplicitThis);
36 | expectType<typeof withImplicitThis>(withExplicitThis);
37 | 


--------------------------------------------------------------------------------
/test-d/simplify-deep.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {SimplifyDeep} from '../index.d.ts';
 3 | 
 4 | type Properties1 = {
 5 | 	height: number;
 6 | 	position: {
 7 | 		top: number;
 8 | 		bottom: number;
 9 | 	};
10 | };
11 | 
12 | type Properties2 = {
13 | 	width: number;
14 | 	position: {
15 | 		left: number;
16 | 		right: number;
17 | 	};
18 | };
19 | 
20 | // Flatten the type output to improve type hints shown in editors.
21 | declare const flattenProperties: {
22 | 	height: number;
23 | 	width: number;
24 | 	position: {
25 | 		top: number;
26 | 		bottom: number;
27 | 		left: number;
28 | 		right: number;
29 | 	};
30 | };
31 | 
32 | expectType<SimplifyDeep<Properties1 & Properties2>>(flattenProperties);
33 | 
34 | // Array
35 | type ArrayType = Array<{
36 | 	a: string;
37 | }>;
38 | 
39 | declare const flattenProperties2: {
40 | 	arrayType: Array<{
41 | 		a: string;
42 | 	}>;
43 | };
44 | expectType<SimplifyDeep<{arrayType: ArrayType}>>(flattenProperties2);
45 | 


--------------------------------------------------------------------------------
/test-d/single-key-object.ts:
--------------------------------------------------------------------------------
 1 | import {expectNever, expectAssignable} from 'tsd';
 2 | import type {SingleKeyObject} from '../index.d.ts';
 3 | 
 4 | const test = <T>(_: SingleKeyObject<T>): void => {}; // eslint-disable-line @typescript-eslint/no-empty-function
 5 | 
 6 | test({key: 'value'});
 7 | 
 8 | // @ts-expect-error
 9 | test({});
10 | // @ts-expect-error
11 | test({key: 'value', otherKey: 'other value'});
12 | 
13 | declare const validObject: SingleKeyObject<{key: string}>;
14 | expectAssignable<{key: string}>(validObject);
15 | 
16 | declare const invalidObject: SingleKeyObject<{key1: string; key2: number}>;
17 | expectNever(invalidObject);
18 | 


--------------------------------------------------------------------------------
/test-d/snake-cased-properties-deep.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {SnakeCasedPropertiesDeep} from '../index.d.ts';
 3 | 
 4 | type FooBar = {helloWorld: {p2p: Array<{addressLine1: string}>}};
 5 | 
 6 | declare const foo: SnakeCasedPropertiesDeep<FooBar>;
 7 | expectType<{hello_world: {p2p: Array<{address_line1: string}>}}>(foo);
 8 | 
 9 | declare const bar: SnakeCasedPropertiesDeep<FooBar, {splitOnNumbers: true}>;
10 | expectType<{hello_world: {p_2_p: Array<{address_line_1: string}>}}>(bar);
11 | 
12 | // Verify example
13 | type User = {
14 | 	userId: number;
15 | 	userName: string;
16 | 	date: Date;
17 | 	regExp: RegExp;
18 | };
19 | 
20 | type UserWithFriends = {
21 | 	userInfo: User;
22 | 	userFriends: User[];
23 | };
24 | 
25 | const result: SnakeCasedPropertiesDeep<UserWithFriends> = {
26 | 	user_info: {
27 | 		user_id: 1,
28 | 		user_name: 'Tom',
29 | 		date: new Date(),
30 | 		reg_exp: /.*/,
31 | 	},
32 | 	user_friends: [
33 | 		{
34 | 			user_id: 2,
35 | 			user_name: 'Jerry',
36 | 			date: new Date(),
37 | 			reg_exp: /.*/,
38 | 		},
39 | 		{
40 | 			user_id: 3,
41 | 			user_name: 'Spike',
42 | 			date: new Date(),
43 | 			reg_exp: /.*/,
44 | 		},
45 | 	],
46 | };
47 | expectType<SnakeCasedPropertiesDeep<UserWithFriends>>(result);
48 | 
49 | expectType<{foo_bar: unknown}>({} as SnakeCasedPropertiesDeep<{fooBar: unknown}>);
50 | expectType<{foo_bar: {bar_baz: unknown}; biz: unknown}>({} as SnakeCasedPropertiesDeep<{fooBar: {barBaz: unknown}; biz: unknown}>);
51 | 
52 | expectType<{foo_bar: any}>({} as SnakeCasedPropertiesDeep<{fooBar: any}>);
53 | expectType<{foo_bar: {bar_baz: any}; biz: any}>({} as SnakeCasedPropertiesDeep<{fooBar: {barBaz: any}; biz: any}>);
54 | 


--------------------------------------------------------------------------------
/test-d/snake-cased-properties.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {SnakeCasedProperties} from '../index.d.ts';
 3 | 
 4 | type Foobar = {helloWorld1: {fooBar: string}};
 5 | 
 6 | declare const foo: SnakeCasedProperties<Foobar>;
 7 | expectType<{hello_world1: {fooBar: string}}>(foo);
 8 | 
 9 | declare const bar: SnakeCasedProperties<Foobar, {splitOnNumbers: true}>;
10 | expectType<{hello_world_1: {fooBar: string}}>(bar);
11 | 
12 | // Verify example
13 | type User = {
14 | 	userId: number;
15 | 	userName: string;
16 | };
17 | const result: SnakeCasedProperties<User> = {
18 | 	user_id: 1,
19 | 	user_name: 'Tom',
20 | };
21 | expectType<SnakeCasedProperties<User>>(result);
22 | 


--------------------------------------------------------------------------------
/test-d/string-slice.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {StringSlice} from '../index.d.ts';
 3 | 
 4 | expectType<StringSlice<'abcde'>>('abcde');
 5 | expectType<StringSlice<'abcde'>>('abcde');
 6 | expectType<StringSlice<'abcde', 0, -1>>('abcd');
 7 | expectType<StringSlice<'abcde', 1, -1>>('bcd');
 8 | expectType<StringSlice<'abcde', 1, 2>>('b');
 9 | expectType<StringSlice<'abcde', 1, 3>>('bc');
10 | expectType<StringSlice<'abcde', -100, -1>>('abcd');
11 | expectType<StringSlice<'abcde', -100, -3>>('ab');
12 | expectType<StringSlice<'abcde', 3, 100>>('de');
13 | expectType<StringSlice<'abcde', 1, 1>>('');
14 | expectType<StringSlice<'abcde', 100, 1>>('');
15 | expectType<StringSlice<string>>(null! as string);
16 | expectType<StringSlice<string, 1>>(null! as string);
17 | expectType<StringSlice<string, 1, 2>>(null! as string);
18 | 


--------------------------------------------------------------------------------
/test-d/stringified.ts:
--------------------------------------------------------------------------------
 1 | import {expectAssignable, expectNotAssignable, expectType} from 'tsd';
 2 | import type {Stringified} from '../index.d.ts';
 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 | expectNotAssignable<Stringified<Car>>({model: 'Foo', speed: 101});
12 | expectAssignable<Stringified<Car>>({model: 'Foo', speed: '101'});
13 | 


--------------------------------------------------------------------------------
/test-d/tagged-union.ts:
--------------------------------------------------------------------------------
 1 | import {expectAssignable, expectNotAssignable} from 'tsd';
 2 | import type {TaggedUnion} from '../index.d.ts';
 3 | 
 4 | type Union = TaggedUnion<'tag', {str: {a: string}; num: {b: number}}>;
 5 | 
 6 | const first = {
 7 | 	tag: 'str' as const,
 8 | 	a: 'some-string',
 9 | };
10 | 
11 | const second = {
12 | 	tag: 'num' as const,
13 | 	b: 1,
14 | };
15 | 
16 | expectAssignable<Union>(first);
17 | expectAssignable<Union>(second);
18 | 
19 | const fails = {
20 | 	tag: 'num' as const,
21 | 	b: 'should not be string',
22 | };
23 | 
24 | const failsToo = {
25 | 	tag: 'str' as const,
26 | 	b: 2,
27 | };
28 | 
29 | expectNotAssignable<Union>(fails);
30 | expectNotAssignable<Union>(failsToo);
31 | 


--------------------------------------------------------------------------------
/test-d/trim.ts:
--------------------------------------------------------------------------------
 1 | import {expectType} from 'tsd';
 2 | import type {Trim} from '../index.d.ts';
 3 | 
 4 | declare function trim<S extends string>(value: S): Trim<S>;
 5 | 
 6 | expectType<'foo'>(trim(' foo'));
 7 | expectType<'bar'>(trim('bar '));
 8 | expectType<'baz'>(trim(' baz '));
 9 | expectType<'waldo'>(trim('  waldo  '));
10 | expectType<'fr ed'>(trim(' fr ed '));
11 | expectType<'foo'>(trim(' foo\n'));
12 | expectType<'foo'>(trim(' foo\n\t '));
13 | 


--------------------------------------------------------------------------------
/test-d/ts41.ts:
--------------------------------------------------------------------------------
1 | // Ensure that TypeScript 4.1 types are available.
2 | import {expectType} from 'tsd';
3 | import type {CamelCase} from '../index.d.ts';
4 | 
5 | const camelFromPascal: CamelCase<'FooBar'> = 'fooBar';
6 | expectType<CamelCase<'FooBar'>>(camelFromPascal);
7 | 


--------------------------------------------------------------------------------
/test-d/tsconfig-json.ts:
--------------------------------------------------------------------------------
 1 | import {expectType, expectAssignable} from 'tsd';
 2 | import type {Jsonifiable, TsConfigJson} from '../index.d.ts';
 3 | 
 4 | const tsConfig: TsConfigJson = {};
 5 | 
 6 | expectType<boolean | undefined>(tsConfig.compileOnSave);
 7 | expectType<TsConfigJson.CompilerOptions | undefined>(tsConfig.compilerOptions);
 8 | expectType<string[] | undefined>(tsConfig.exclude);
 9 | expectType<string | string[] | undefined>(tsConfig.extends);
10 | expectType<string[] | undefined>(tsConfig.files);
11 | expectType<string[] | undefined>(tsConfig.include);
12 | expectType<TsConfigJson.References[] | undefined>(tsConfig.references);
13 | expectType<TsConfigJson.TypeAcquisition | undefined>(tsConfig.typeAcquisition);
14 | expectAssignable<Jsonifiable>(tsConfig);
15 | 
16 | expectType<boolean | undefined>(tsConfig.compilerOptions?.noCheck);
17 | 


--------------------------------------------------------------------------------
/test-d/tuple-to-union.ts:
--------------------------------------------------------------------------------
 1 | import {expectAssignable, expectNotType, expectType} from 'tsd';
 2 | import type {TupleToUnion} from '../index.d.ts';
 3 | 
 4 | const options = ['a', 'b', 'c'] as const;
 5 | type Options = TupleToUnion<typeof options>;
 6 | 
 7 | const a: Options = 'a';
 8 | expectAssignable<Options>(a);
 9 | expectType<'a'>(a);
10 | expectNotType<'b'>(a);
11 | expectNotType<'c'>(a);
12 | 
13 | const b: Options = 'b';
14 | expectAssignable<Options>(b);
15 | expectNotType<'a'>(b);
16 | expectType<'b'>(b);
17 | expectNotType<'c'>(b);
18 | 
19 | const c: Options = 'c';
20 | expectAssignable<Options>(c);
21 | expectNotType<'a'>(c);
22 | expectNotType<'b'>(c);
23 | expectType<'c'>(c);
24 | 
25 | declare const notAnArray: TupleToUnion<[]>;
26 | expectType<never>(notAnArray);
27 | 
28 | declare const worksWithArrays: TupleToUnion<Array<string | number>>;
29 | expectType<string | number>(worksWithArrays);
30 | 
31 | declare const resolvesToNeverForNonArrays: TupleToUnion<string | number>;
32 | expectType<never>(resolvesToNeverForNonArrays);
33 | 
34 | declare const infiniteRestArguments: TupleToUnion<[string, ...number[]]>;
35 | expectType<string | number>(infiniteRestArguments);
36 | 


--------------------------------------------------------------------------------
/test-d/union-to-intersection.ts:
--------------------------------------------------------------------------------
 1 | import {expectAssignable, expectType} from 'tsd';
 2 | import type {UnionToIntersection} from '../index.d.ts';
 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 | 
11 | // It's possible to index by the resulting type.
12 | type ObjectsUnion = {a: string; z: string} | {b: string; z: string} | {c: string; z: string};
13 | declare const value: ObjectsUnion[UnionToIntersection<keyof ObjectsUnion>];
14 | expectType<string>(value);
15 | 


--------------------------------------------------------------------------------
/test-d/union-to-tuple.ts:
--------------------------------------------------------------------------------
 1 | import {expectAssignable, expectType} from 'tsd';
 2 | import type {UnionToTuple} from '../index.d.ts';
 3 | 
 4 | type Options = UnionToTuple<'a' | 'b' | 'c'>;
 5 | // Results unordered
 6 | expectAssignable<['a', 'b', 'c'] | ['a', 'c', 'b'] | ['b', 'a', 'c'] | ['b', 'c', 'a'] | ['c', 'a', 'b'] | ['c', 'b', 'a']>({} as Options);
 7 | expectType<Options[number]>({} as ('a' | 'b' | 'c'));
 8 | 
 9 | type Options1 = UnionToTuple<1 | 2 | 3>;
10 | expectType<Options1[number]>({} as (1 | 2 | 3));
11 | 
12 | type Options2 = UnionToTuple<boolean | 1>;
13 | expectType<Options2[number]>({} as (1 | false | true));
14 | 


--------------------------------------------------------------------------------
/test-d/unknown-array.ts:
--------------------------------------------------------------------------------
 1 | import {expectAssignable, expectNotAssignable, expectType} from 'tsd';
 2 | import type {UnknownArray} from '../index.d.ts';
 3 | 
 4 | declare const foo: readonly [];
 5 | declare const bar: {
 6 | 	readonly array: unknown[];
 7 | };
 8 | 
 9 | expectAssignable<UnknownArray>(foo);
10 | expectAssignable<UnknownArray>(bar.array);
11 | expectAssignable<UnknownArray>([]);
12 | expectAssignable<UnknownArray>(['foo']);
13 | 
14 | expectNotAssignable<UnknownArray>(null);
15 | expectNotAssignable<UnknownArray>(undefined);
16 | expectNotAssignable<UnknownArray>({});
17 | expectNotAssignable<UnknownArray>({0: 1});
18 | expectNotAssignable<UnknownArray>(1);
19 | expectNotAssignable<UnknownArray>(Date);
20 | 
21 | type IsArray<T> = T extends UnknownArray ? true : false;
22 | 
23 | declare const string: IsArray<string>;
24 | expectType<false>(string);
25 | declare const array: IsArray<[]>;
26 | expectType<true>(array);
27 | declare const tuple: IsArray<['foo']>;
28 | expectType<true>(tuple);
29 | declare const readonlyArray: IsArray<readonly number[]>;
30 | expectType<true>(readonlyArray);
31 | declare const leadingSpread: IsArray<readonly [number, ...string[]]>;
32 | expectType<true>(leadingSpread);
33 | declare const trailingSpread: IsArray<readonly [...string[], number]>;
34 | expectType<true>(trailingSpread);
35 | 


--------------------------------------------------------------------------------
/test-d/unknown-map.ts:
--------------------------------------------------------------------------------
 1 | import {expectAssignable, expectNotAssignable} from 'tsd';
 2 | import type {UnknownMap} from '../index.d.ts';
 3 | 
 4 | declare const foo: ReadonlyMap<string, number>;
 5 | declare const bar: {
 6 | 	readonly map: ReadonlyMap<number, string>;
 7 | };
 8 | 
 9 | expectAssignable<UnknownMap>(foo);
10 | expectAssignable<UnknownMap>(bar.map);
11 | expectAssignable<UnknownMap>(new Map());
12 | expectAssignable<UnknownMap>(new Map([['foo', 1]]));
13 | 
14 | expectNotAssignable<UnknownMap>(null);
15 | expectNotAssignable<UnknownMap>(undefined);
16 | expectNotAssignable<UnknownMap>({});
17 | expectNotAssignable<UnknownMap>([]);
18 | expectNotAssignable<UnknownMap>({0: 1});
19 | expectNotAssignable<UnknownMap>(1);
20 | 


--------------------------------------------------------------------------------
/test-d/unknown-record.ts:
--------------------------------------------------------------------------------
 1 | import {expectAssignable, expectType} from 'tsd';
 2 | import type {UnknownRecord} from '../index.d.ts';
 3 | 
 4 | declare let foo: UnknownRecord;
 5 | 
 6 | expectAssignable<UnknownRecord>(foo);
 7 | expectAssignable<UnknownRecord>(foo = {});
 8 | expectAssignable<UnknownRecord>(foo = {bar: 'baz'});
 9 | expectAssignable<UnknownRecord>(foo = {bar: {baz: 'hello'}});
10 | 
11 | // @ts-expect-error
12 | foo = [];
13 | // @ts-expect-error
14 | foo = 42;
15 | // @ts-expect-error
16 | foo = null;
17 | 
18 | expectType<unknown>(foo['bar']);
19 | 


--------------------------------------------------------------------------------
/test-d/unknown-set.ts:
--------------------------------------------------------------------------------
 1 | import {expectAssignable, expectNotAssignable} from 'tsd';
 2 | import type {UnknownSet} from '../index.d.ts';
 3 | 
 4 | declare const foo: ReadonlySet<string>;
 5 | declare const bar: {
 6 | 	readonly set: ReadonlySet<number>;
 7 | };
 8 | 
 9 | expectAssignable<UnknownSet>(foo);
10 | expectAssignable<UnknownSet>(bar.set);
11 | expectAssignable<UnknownSet>(new Set());
12 | expectAssignable<UnknownSet>(new Set('foo'));
13 | 
14 | expectNotAssignable<UnknownSet>(null);
15 | expectNotAssignable<UnknownSet>(undefined);
16 | expectNotAssignable<UnknownSet>({});
17 | expectNotAssignable<UnknownSet>([]);
18 | expectNotAssignable<UnknownSet>({0: 1});
19 | expectNotAssignable<UnknownSet>(1);
20 | expectNotAssignable<UnknownSet>(Date);
21 | 


--------------------------------------------------------------------------------
/test-d/value-of.ts:
--------------------------------------------------------------------------------
 1 | import {expectAssignable, expectNotAssignable, expectType} from 'tsd';
 2 | import type {ValueOf} from '../index.d.ts';
 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 | expectNotAssignable<4>(value);
 9 | 
10 | expectType<1>(valueRestricted);
11 | expectNotAssignable<2>(valueRestricted);
12 | expectNotAssignable<4>(valueRestricted);
13 | 


--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
 1 | {
 2 | 	"extends": "@sindresorhus/tsconfig",
 3 | 	"compilerOptions": {
 4 | 		"noEmit": true,
 5 | 		"allowJs": true,
 6 | 		"noUnusedLocals": false, // Allow unused variables in test-d/*.ts files
 7 | 		"module": "node18",
 8 | 		"target": "ES2023", // Node.js 20
 9 | 		"lib": [
10 | 			"ES2023",
11 | 			"DOM"
12 | 		],
13 | 		"types": [], // Ensures no @types/ are unintentionally included
14 | 		"exactOptionalPropertyTypes": true,
15 | 		"skipLibCheck": false, // Ensures .d.ts files are checked: https://github.com/sindresorhus/tsconfig/issues/15
16 | 	}
17 | }
18 | 


--------------------------------------------------------------------------------