Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PartialDeep: Add allowUndefinedInArrays option #1019

Merged
26 changes: 24 additions & 2 deletions source/partial-deep.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ export type PartialDeepOptions = {
@default false
*/
readonly recurseIntoArrays?: boolean;

/**
Whether to authorize undefined values in arrays and tuples.
PicoI2 marked this conversation as resolved.
Show resolved Hide resolved

@default true
*/
readonly allowUndefinedInArrays?: boolean;
PicoI2 marked this conversation as resolved.
Show resolved Hide resolved
};

/**
Expand Down Expand Up @@ -54,6 +61,21 @@ const partialSettings: PartialDeep<Settings, {recurseIntoArrays: true}> = {
};
```

You can prevent undefined values in recurse arrays and tuples by passing `{recurseIntoArrays: true; allowUndefinedInArrays: false}` as the second type argument:

```
import type {PartialDeep} from 'type-fest';

interface Settings {
languages: string[];
}

const partialSettings: PartialDeep<Settings, {recurseIntoArrays: true; allowUndefinedInArrays: false}> = {
languages: [undefined] // Error
languages: [] // OK
};
```

PicoI2 marked this conversation as resolved.
Show resolved Hide resolved
@category Object
@category Array
@category Set
Expand All @@ -74,8 +96,8 @@ export type PartialDeep<T, Options extends PartialDeepOptions = {}> = T extends
? 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>>
? ReadonlyArray<PartialDeep<Options['allowUndefinedInArrays'] extends false ? ItemType : ItemType | undefined, Options>>
: Array<PartialDeep<Options['allowUndefinedInArrays'] extends false ? ItemType : 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>
Expand Down
8 changes: 8 additions & 0 deletions test-d/partial-deep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,14 @@ expectAssignable<PartialDeep<RecurseObject>>(recurseObject);
const partialDeepNoRecurseIntoArraysFoo: PartialDeep<typeof foo> = foo;
// Check that `{recurseIntoArrays: true}` behaves as intended
expectType<PartialDeep<typeof foo, {recurseIntoArrays: true}>>(partialDeepFoo);

// Check that `{allowUndefinedInArrays: true}` is the default
const partialDeepAllowUndefinedInArraysFoo: PartialDeep<typeof foo, {recurseIntoArrays: true}> = foo;
expectType<Array<string | undefined> | undefined>(partialDeepAllowUndefinedInArraysFoo.bar!.array);
// Check that `{allowUndefinedInArrays: false}` behaves as intended
const partialDeepDoNotAllowUndefinedInArraysFoo: PartialDeep<typeof foo, {recurseIntoArrays: true; allowUndefinedInArrays: false}> = foo;
expectType<string[] | undefined>(partialDeepDoNotAllowUndefinedInArraysFoo.bar!.array);

// These are mostly the same checks as before, but the array/tuple types are different.
// @ts-expect-error
expectType<Partial<typeof foo>>(partialDeepNoRecurseIntoArraysFoo);
Expand Down
Loading