Skip to content

Commit

Permalink
feat(#102): finish DeepNonRequired<T>
Browse files Browse the repository at this point in the history
  • Loading branch information
AshGw committed Apr 26, 2024
1 parent fe1ddfa commit f85b154
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 0 deletions.
50 changes: 50 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1625,6 +1625,56 @@ export type DeepRequired<T> = T extends UnknownFunction
*/
export type IsDeepRequired<T> = IfExtends<T, DeepRequired<T>, true, false>;

/**
* Why not call it ``DeepOptional``?
* ``Optional<T>`` in this library represents a type ``T`` that can be either ``T`` or ``null``. So creating
* ``DeepOptional`` type would entail adding null to every property, which is not the intention here.
*
* ``DeepNonRequired<T>`` turns all required keys in a given object (nested) to non required one.
* non required as in: marked with `?` operator
* @example
* ```ts
type Actual = {
a: () => 1;
x: string;
s: {
q: Nullable;
s: {
i: {
x: {
o: Maybe<Primitive>;
n: Falsy;
};
e: 'foo';
};
};
};
};
type Expected = {
a?: () => 1;
x?: string;
s?: {
q?: Nullable;
s?: {
i?: {
x?: {
o?: Maybe<Primitive>;
n?: Falsy;
};
e?: 'foo';
};
};
};
};
type T = DeepNonRequired<Actual>; // Result: Expected
* ```
*/
export type DeepNonRequired<T> = T extends UnknownFunction
? T
: {
[K in Keys<T>]+?: IfExtends<T[K], unknown, DeepNonRequired<T[K]>, T[K]>;
};
/**
* @hidden
*/
Expand Down
48 changes: 48 additions & 0 deletions tests/deep-non-required.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import {
Falsy,
DeepNonRequired,
Primitive,
Maybe,
Nullable,
TestType,
} from 'src';
import { test, expect } from 'vitest';

type Actual = {
a: () => 1;
x: string;
s: {
q: Nullable;
s: {
i: {
x: {
o: Maybe<Primitive>;
n: Falsy;
};
e: 'foo';
};
};
};
};

type Expected = {
a?: () => 1;
x?: string;
s?: {
q?: Nullable;
s?: {
i?: {
x?: {
o?: Maybe<Primitive>;
n?: Falsy;
};
e?: 'foo';
};
};
};
};

test('_', () => {
const result: TestType<DeepNonRequired<Actual>, Expected, true> = true;
expect(result).toBe(true);
});

0 comments on commit f85b154

Please sign in to comment.