Skip to content

Commit

Permalink
fix(typescript): improve typings for partials
Browse files Browse the repository at this point in the history
  • Loading branch information
Vittorio committed Jun 19, 2023
1 parent 0197d87 commit 28ad22a
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 25 deletions.
10 changes: 10 additions & 0 deletions src/partial/internal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
export type Primitive =
| null
| undefined
| string
| number
| boolean
| symbol
| bigint;

export type BuiltIns = Primitive | Date | RegExp;
45 changes: 20 additions & 25 deletions src/partial/partial.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
type Primitive = null | undefined | string | number | boolean | symbol | bigint;
import type { BuiltIns } from './internal';

export type PartialDeep<T> = T extends Primitive
? Partial<T>
export type PartialDeep<T> = T extends BuiltIns
? T
: T extends Map<infer KeyType, infer ValueType>
? PartialMapDeep<KeyType, ValueType>
: T extends Set<infer ItemType>
Expand All @@ -13,34 +13,29 @@ export type PartialDeep<T> = T extends Primitive
: T extends (...args: any[]) => unknown // eslint-disable-line @typescript-eslint/no-explicit-any
? T | undefined
: T extends object
? PartialObjectDeep<T>
? T extends ReadonlyArray<infer ItemType> // Test for arrays/tuples, per https://github.com/microsoft/TypeScript/issues/35156
? ItemType[] extends T // Test for arrays (non-tuples) specifically
? readonly ItemType[] extends T // Differentiate readonly and mutable arrays
? ReadonlyArray<PartialDeep<ItemType | undefined>>
: Array<PartialDeep<ItemType | undefined>>
: PartialObjectDeep<T>
: PartialObjectDeep<T>
: unknown;

/**
Same as `PartialDeep`, but accepts only `Map`s and as inputs. Internal helper for `PartialDeep`.
*/
interface PartialMapDeep<KeyType, ValueType>
extends Map<PartialDeep<KeyType>, PartialDeep<ValueType>> {}
type PartialMapDeep<KeyType, ValueType> = {} & Map<
PartialDeep<KeyType>,
PartialDeep<ValueType>
>;

/**
Same as `PartialDeep`, but accepts only `Set`s as inputs. Internal helper for `PartialDeep`.
*/
interface PartialSetDeep<T> extends Set<PartialDeep<T>> {}
type PartialSetDeep<T> = {} & Set<PartialDeep<T>>;

/**
Same as `PartialDeep`, but accepts only `ReadonlyMap`s as inputs. Internal helper for `PartialDeep`.
*/
interface PartialReadonlyMapDeep<KeyType, ValueType>
extends ReadonlyMap<PartialDeep<KeyType>, PartialDeep<ValueType>> {}
type PartialReadonlyMapDeep<KeyType, ValueType> = {} & ReadonlyMap<
PartialDeep<KeyType>,
PartialDeep<ValueType>
>;

/**
Same as `PartialDeep`, but accepts only `ReadonlySet`s as inputs. Internal helper for `PartialDeep`.
*/
interface PartialReadonlySetDeep<T> extends ReadonlySet<PartialDeep<T>> {}
type PartialReadonlySetDeep<T> = {} & ReadonlySet<PartialDeep<T>>;

/**
Same as `PartialDeep`, but accepts only `object`s as inputs. Internal helper for `PartialDeep`.
*/
type PartialObjectDeep<ObjectType extends object> = {
[KeyType in keyof SuppressObjectPrototypeOverrides<ObjectType>]?: PartialDeep<
SuppressObjectPrototypeOverrides<ObjectType>[KeyType]
Expand Down

0 comments on commit 28ad22a

Please sign in to comment.