Skip to content

Commit

Permalink
Work around TypeScript limitation with the PartialDeep type (#296)
Browse files Browse the repository at this point in the history
  • Loading branch information
merrywhether committed Oct 17, 2021
1 parent 98158e0 commit 065e764
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 2 deletions.
6 changes: 5 additions & 1 deletion source/partial-deep.d.ts
Expand Up @@ -43,7 +43,11 @@ export type PartialDeep<T> = T extends Primitive
: T extends ((...arguments: any[]) => unknown)
? T | undefined
: T extends object
? PartialObjectDeep<T>
? T extends Array<infer ItemType> // Test for arrays/tuples, per https://github.com/microsoft/TypeScript/issues/35156
? ItemType[] extends T // Test for arrays (non-tuples) specifically
? Array<PartialDeep<ItemType | undefined>> // Recreate relevant array type to prevent eager evaluation of circular reference
: PartialObjectDeep<T> // Tuples behave properly
: PartialObjectDeep<T>
: unknown;

/**
Expand Down
14 changes: 13 additions & 1 deletion test-d/partial-deep.ts
Expand Up @@ -4,7 +4,7 @@ import {PartialDeep} from '../index';
const foo = {
baz: 'fred',
bar: {
function: (_: string): void => {}, // eslint-disable-line @typescript-eslint/no-empty-function
function: (_: string): void => undefined,
object: {key: 'value'},
string: 'waldo',
number: 1,
Expand Down Expand Up @@ -47,3 +47,15 @@ expectType<readonly ['foo'?] | undefined>(partialDeepFoo.bar!.readonlyTuple);
// Check for compiling with omitting partial keys
partialDeepFoo = {baz: 'fred'};
partialDeepFoo = {bar: {string: 'waldo'}};

// Check that recursive array evalution isn't infinite depth
type Recurse =
| string
| number
| boolean
| null
| Record<string, Recurse[]>
| Recurse[];
type RecurseObject = {value: Recurse};
const recurseObject: RecurseObject = {value: null};
expectAssignable<PartialDeep<RecurseObject>>(recurseObject);

0 comments on commit 065e764

Please sign in to comment.