Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: sindresorhus/type-fest
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v4.6.0
Choose a base ref
...
head repository: sindresorhus/type-fest
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v4.7.0
Choose a head ref
  • 9 commits
  • 19 files changed
  • 3 contributors

Commits on Oct 25, 2023

  1. Add SetFieldType type (#721)

    Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
    lucasteles and sindresorhus authored Oct 25, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    964466c View commit details

Commits on Oct 26, 2023

  1. Writable: Support array, map, and set (#726)

    Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
    Emiyaaaaa and sindresorhus authored Oct 26, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    b9723d4 View commit details

Commits on Oct 30, 2023

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    9960ba4 View commit details

Commits on Nov 2, 2023

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    5eeac02 View commit details

Commits on Nov 4, 2023

  1. Add UnknownArray type (#740)

    Emiyaaaaa authored Nov 4, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    30aa0ad View commit details

Commits on Nov 7, 2023

  1. Add Paths type (#741)

    Emiyaaaaa authored Nov 7, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    996171b View commit details

Commits on Nov 8, 2023

  1. Meta tweaks

    sindresorhus committed Nov 8, 2023
    Copy the full SHA
    86ddc1a View commit details
  2. Add PickDeep type (#737)

    Co-authored-by: Sindre Sorhus <sindresorhus@gmail.com>
    Emiyaaaaa and sindresorhus authored Nov 8, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    c60caba View commit details
  3. 4.7.0

    sindresorhus committed Nov 8, 2023
    Copy the full SHA
    af160e8 View commit details
8 changes: 4 additions & 4 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -14,8 +14,8 @@ jobs:
- 18
- 16
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm install
@@ -31,8 +31,8 @@ jobs:
- "~5.2.0"
- "~5.1.0"
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 18
- run: npm install
4 changes: 4 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -9,6 +9,7 @@ export type {KeysOfUnion} from './source/keys-of-union';
export type {EmptyObject, IsEmptyObject} from './source/empty-object';
export type {NonEmptyObject} from './source/non-empty-object';
export type {UnknownRecord} from './source/unknown-record';
export type {UnknownArray} from './source/unknown-array';
export type {Except} from './source/except';
export type {TaggedUnion} from './source/tagged-union';
export type {Writable} from './source/writable';
@@ -24,6 +25,7 @@ export type {OmitIndexSignature} from './source/omit-index-signature';
export type {PickIndexSignature} from './source/pick-index-signature';
export type {PartialDeep, PartialDeepOptions} from './source/partial-deep';
export type {RequiredDeep} from './source/required-deep';
export type {PickDeep} from './source/pick-deep';
export type {PartialOnUndefinedDeep, PartialOnUndefinedDeepOptions} from './source/partial-on-undefined-deep';
export type {UndefinedOnPartialDeep} from './source/undefined-on-partial-deep';
export type {ReadonlyDeep} from './source/readonly-deep';
@@ -101,6 +103,8 @@ export type {IsUnknown} from './source/is-unknown';
export type {IfUnknown} from './source/if-unknown';
export type {ArrayIndices} from './source/array-indices';
export type {ArrayValues} from './source/array-values';
export type {SetFieldType} from './source/set-field-type';
export type {Paths} from './source/paths';

// Template literal types
export type {CamelCase} from './source/camel-case';
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "type-fest",
"version": "4.6.0",
"version": "4.7.0",
"description": "A collection of essential TypeScript types",
"license": "(MIT OR CC0-1.0)",
"repository": "sindresorhus/type-fest",
@@ -11,6 +11,7 @@
"url": "https://sindresorhus.com"
},
"types": "./index.d.ts",
"sideEffects": false,
"engines": {
"node": ">=16"
},
6 changes: 5 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
@@ -113,8 +113,9 @@ Click the type names for complete docs.
- [`IsEmptyObject`](source/empty-object.d.ts) - Returns a `boolean` for whether the type is strictly equal to an empty plain object, the `{}` value.
- [`NonEmptyObject`](source/non-empty-object.d.ts) - Represents an object with at least 1 non-optional key.
- [`UnknownRecord`](source/unknown-record.d.ts) - Represents an object with `unknown` value. You probably want this instead of `{}`.
- [`UnknownArray`](source/unknown-array.d.ts) - Represents an array with `unknown` value.
- [`Except`](source/except.d.ts) - Create a type from an object type without certain keys. This is a stricter version of [`Omit`](https://www.typescriptlang.org/docs/handbook/utility-types.html#omittype-keys).
- [`Writable`](source/writable.d.ts) - Create a type that strips `readonly` from all or some of an object's keys. The inverse of `Readonly<T>`.
- [`Writable`](source/writable.d.ts) - Create a type that strips `readonly` from the given type. Inverse of `Readonly<T>`.
- [`WritableDeep`](source/writable-deep.d.ts) - Create a deeply mutable version of an `object`/`ReadonlyMap`/`ReadonlySet`/`ReadonlyArray` type. The inverse of `ReadonlyDeep<T>`. Use `Writable<T>` if you only need one level deep.
- [`Merge`](source/merge.d.ts) - Merge two types into a new type. Keys of the second type overrides keys of the first type.
- [`MergeDeep`](source/merge-deep.d.ts) - Merge two objects or two arrays/tuples recursively into a new type.
@@ -125,6 +126,7 @@ Click the type names for complete docs.
- [`RequireAllOrNone`](source/require-all-or-none.d.ts) - Create a type that requires all of the given keys or none of the given keys.
- [`RequireOneOrNone`](source/require-one-or-none.d.ts) - Create a type that requires exactly a single key of the given keys and disallows more, or none of the given keys.
- [`RequiredDeep`](source/required-deep.d.ts) - Create a deeply required version of another type. Use [`Required<T>`](https://www.typescriptlang.org/docs/handbook/utility-types.html#requiredtype) if you only need one level deep.
- [`PickDeep`](source/pick-deep.d.ts) - Pick properties from a deeply-nested object. Use [`Pick<T>`](https://www.typescriptlang.org/docs/handbook/utility-types.html#picktype-keys) if you only need one level deep.
- [`OmitIndexSignature`](source/omit-index-signature.d.ts) - Omit any index signatures from the given object type, leaving only explicitly defined properties.
- [`PickIndexSignature`](source/pick-index-signature.d.ts) - Pick only index signatures from the given object type, leaving out all explicitly defined properties.
- [`PartialDeep`](source/partial-deep.d.ts) - Create a deeply optional version of another type. Use [`Partial<T>`](https://www.typescriptlang.org/docs/handbook/utility-types.html#partialtype) if you only need one level deep.
@@ -175,6 +177,8 @@ Click the type names for complete docs.
- [`IntRange`](source/int-range.d.ts) - Generate a union of numbers.
- [`ArrayIndices`](source/array-indices.d.ts) - Provides valid indices for a constant array or tuple.
- [`ArrayValues`](source/array-values.d.ts) - Provides all values for a constant array or tuple.
- [`SetFieldType`](source/set-field-type.d.ts) - Create a type that changes the type of the given keys.
- [`Paths`](source/paths.d.ts) - Generate a union of all possible paths to properties in the given object.

### Type Guard

6 changes: 4 additions & 2 deletions source/conditional-pick-deep.d.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import type {IsEqual} from './is-equal';
import type {ConditionalExcept} from './conditional-except';
import type {ConditionalSimplifyDeep} from './conditional-simplify';
import type {UnknownRecord} from './unknown-record';
import type {EmptyObject} from './empty-object';

/**
Used to mark properties that should be excluded.
@@ -95,7 +97,7 @@ export type ConditionalPickDeep<
> = ConditionalSimplifyDeep<ConditionalExcept<{
[Key in keyof Type]: AssertCondition<Type[Key], Condition, Options> extends true
? Type[Key]
: Type[Key] extends object
: Type[Key] extends UnknownRecord
? ConditionalPickDeep<Type[Key], Condition, Options>
: typeof conditionalPickDeepSymbol;
}, (typeof conditionalPickDeepSymbol | undefined) | Record<PropertyKey, never>>>;
}, (typeof conditionalPickDeepSymbol | undefined) | EmptyObject>, never, UnknownRecord>;
32 changes: 32 additions & 0 deletions source/internal.d.ts
Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@ import type {Primitive} from './primitive';
import type {Simplify} from './simplify';
import type {Trim} from './trim';
import type {IsAny} from './is-any';
import type {UnknownRecord} from './unknown-record';

// TODO: Remove for v5.
export type {UnknownRecord} from './unknown-record';
@@ -24,6 +25,37 @@ export type BuildTuple<L extends number, Fill = unknown, T extends readonly unkn
? T
: BuildTuple<L, Fill, [...T, Fill]>;

/**
Create an object type with the given key `<Key>` and value `<Value>`.
It will copy the prefix and optional status of the same key from the given object `CopiedFrom` into the result.
@example
```
type A = BuildObject<'a', string>;
//=> {a: string}
// Copy `readonly` and `?` from the key `a` of `{readonly a?: any}`
type B = BuildObject<'a', string, {readonly a?: any}>;
//=> {readonly a?: string}
```
*/
export type BuildObject<Key extends PropertyKey, Value, CopiedFrom extends UnknownRecord = {}> =
Key extends keyof CopiedFrom
? Pick<{[_ in keyof CopiedFrom]: Value}, Key>
: Key extends `${infer NumberKey extends number}`
? NumberKey extends keyof CopiedFrom
? Pick<{[_ in keyof CopiedFrom]: Value}, NumberKey>
: {[_ in Key]: Value}
: {[_ in Key]: Value};

/**
Return a string representation of the given string or number.
Note: This type is not the return type of the `.toString()` function.
*/
export type ToString<T> = T extends string | number ? `${T}` : never;

/**
Create a tuple of length `A` and a tuple composed of two other tuples,
the inferred tuple `U` and a tuple of length `B`, then extracts the length of tuple `U`.
10 changes: 5 additions & 5 deletions source/partial-deep.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type {BuiltIns} from './internal';
import type {BuiltIns, UnknownRecord} from './internal';

/**
@see PartialDeep
@@ -69,17 +69,17 @@ export type PartialDeep<T, Options extends PartialDeepOptions = {}> = T extends
? PartialReadonlyMapDeep<KeyType, ValueType, Options>
: T extends ReadonlySet<infer ItemType>
? PartialReadonlySetDeep<ItemType, Options>
: T extends object
? T extends ReadonlyArray<infer ItemType> // Test for arrays/tuples, per https://github.com/microsoft/TypeScript/issues/35156
: T extends UnknownRecord
? PartialObjectDeep<T, Options>
: T extends ReadonlyArray<infer ItemType> // Test for arrays/tuples, per https://github.com/microsoft/TypeScript/issues/35156
? Options['recurseIntoArrays'] extends true
? ItemType[] extends T // Test for arrays (non-tuples) specifically
? readonly ItemType[] extends T // Differentiate readonly and mutable arrays
? ReadonlyArray<PartialDeep<ItemType | undefined, Options>>
: Array<PartialDeep<ItemType | undefined, Options>>
: PartialObjectDeep<T, Options> // Tuples behave properly
: T // If they don't opt into array testing, just use the original type
: PartialObjectDeep<T, Options>
: unknown;
: T;

/**
Same as `PartialDeep`, but accepts only `Map`s and as inputs. Internal helper for `PartialDeep`.
107 changes: 107 additions & 0 deletions source/paths.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
import type {ToString} from './internal';
import type {EmptyObject} from './empty-object';
import type {IsAny} from './is-any';
import type {IsNever} from './is-never';
import type {UnknownArray} from './unknown-array';
import type {UnknownRecord} from './unknown-record';

/**
Return the part of the given array with a fixed index.
@example
```
type A = [string, number, boolean, ...string[]];
type B = FilterFixedIndexArray<A>;
//=> [string, number, boolean]
```
*/
type FilterFixedIndexArray<T extends UnknownArray, Result extends UnknownArray = []> =
number extends T['length'] ?
T extends readonly [infer U, ...infer V]
? FilterFixedIndexArray<V, [...Result, U]>
: Result
: T;

/**
Return the part of the given array with a non-fixed index.
@example
```
type A = [string, number, boolean, ...string[]];
type B = FilterNotFixedIndexArray<A>;
//=> string[]
```
*/
type FilterNotFixedIndexArray<T extends UnknownArray> =
T extends readonly [...FilterFixedIndexArray<T>, ...infer U]
? U
: [];

/**
Generate a union of all possible paths to properties in the given object.
It also works with arrays.
Use-case: You want a type-safe way to access deeply nested properties in an object.
@example
```
import type {Paths} from 'type-fest';
type Project = {
filename: string;
listA: string[];
listB: [{filename: string}];
folder: {
subfolder: {
filename: string;
};
};
};
type ProjectPaths = Paths<Project>;
//=> 'filename' | 'listA' | 'listB' | 'folder' | `listA.${number}` | 'listB.0' | 'listB.0.filename' | 'folder.subfolder' | 'folder.subfolder.filename'
declare function open<Path extends ProjectPaths>(path: Path): void;
open('filename'); // Pass
open('folder.subfolder'); // Pass
open('folder.subfolder.filename'); // Pass
open('foo'); // TypeError
// Also works with arrays
open('listA.1'); // Pass
open('listB.0'); // Pass
open('listB.1'); // TypeError. Because listB only has one element.
```
@category Object
@category Array
*/
export type Paths<T extends UnknownRecord | UnknownArray> =
IsAny<T> extends true
? never
: T extends UnknownArray
? number extends T['length']
// We need to handle the fixed and non-fixed index part of the array separately.
? InternalPaths<FilterFixedIndexArray<T>>
| InternalPaths<Array<FilterNotFixedIndexArray<T>[number]>>
: InternalPaths<T>
: InternalPaths<T>;

export type InternalPaths<_T extends UnknownRecord | UnknownArray, T = Required<_T>> =
T extends EmptyObject | readonly []
? never
: {
[Key in keyof T]:
Key extends string | number // Limit `Key` to string or number.
? T[Key] extends UnknownRecord | UnknownArray
? (
IsNever<Paths<T[Key]>> extends false
// If `Key` is a number, return `Key | `${Key}``, because both `array[0]` and `array['0']` work.
? Key | ToString<Key> | `${Key}.${Paths<T[Key]>}`
: Key | ToString<Key>
)
: Key | ToString<Key>
: never
}[keyof T & (T extends UnknownArray ? number : unknown)];
Loading