Skip to content

Commit

Permalink
Add SetNonNullable type (#431)
Browse files Browse the repository at this point in the history
  • Loading branch information
JohannCooper committed Aug 22, 2022
1 parent 1f0e772 commit 1a69e63
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 0 deletions.
1 change: 1 addition & 0 deletions index.d.ts
Expand Up @@ -23,6 +23,7 @@ export {Opaque, UnwrapOpaque} from './source/opaque';
export {InvariantOf} from './source/invariant-of';
export {SetOptional} from './source/set-optional';
export {SetRequired} from './source/set-required';
export {SetNonNullable} from './source/set-non-nullable';
export {ValueOf} from './source/value-of';
export {PromiseValue} from './source/promise-value';
export {AsyncReturnType} from './source/async-return-type';
Expand Down
1 change: 1 addition & 0 deletions readme.md
Expand Up @@ -142,6 +142,7 @@ Click the type names for complete docs.
- [`InvariantOf`](source/invariant-of.d.ts) - Create an [invariant type](https://basarat.gitbook.io/typescript/type-system/type-compatibility#footnote-invariance), which is a type that does not accept supertypes and subtypes.
- [`SetOptional`](source/set-optional.d.ts) - Create a type that makes the given keys optional.
- [`SetRequired`](source/set-required.d.ts) - Create a type that makes the given keys required.
- [`SetNonNullable`](source/set-non-nullable.d.ts) - Create a type that makes the given keys non-nullable.
- [`ValueOf`](source/value-of.d.ts) - Create a union of the given object's values, and optionally specify which keys to get the values from.
- [`ConditionalKeys`](source/conditional-keys.d.ts) - Extract keys from a shape where values extend the given `Condition` type.
- [`ConditionalPick`](source/conditional-pick.d.ts) - Like `Pick` except it selects properties from a shape where the values extend the given `Condition` type.
Expand Down
35 changes: 35 additions & 0 deletions source/set-non-nullable.d.ts
@@ -0,0 +1,35 @@
import type {Except} from './except';
import type {Simplify} from './simplify';

/**
Create a type that makes the given keys non-nullable. The remaining keys are kept as is.
Use-case: You want to define a single model where the only thing that changes is whether or not some of the keys are non-nullable.
@example
```
import type {SetNonNullable} from 'type-fest';
type Foo = {
a: number;
b: string | undefined;
c?: boolean | null;
}
type SomeNonNullable = SetNonNullable<Foo, 'b' | 'c'>;
// type SomeNonNullable = {
// a: number;
// b: string; // Can no longer be undefined.
// c?: boolean; // Can no longer be null, but is still optional.
// }
```
@category Object
*/
export type SetNonNullable<BaseType, Keys extends keyof BaseType> =
Simplify<
// Pick just the keys that are readonly from the base type.
Except<BaseType, Keys> &
// Pick the keys that should be non-nullable from the base type and make them non-nullable.
{[Key in Keys]: NonNullable<BaseType[Key]>}
>;
18 changes: 18 additions & 0 deletions test-d/set-non-nullable.ts
@@ -0,0 +1,18 @@
import {expectType, expectError} from 'tsd';
import type {SetNonNullable} from '../index';

// Update one possibly undefined key and one possibly null key to non-nullable.
declare const variation1: SetNonNullable<{a: number; b: string | undefined; c: boolean | null}, 'b' | 'c'>;
expectType<{a: number; b: string; c: boolean}>(variation1);

// Update a key that is possibly null or undefined.
declare const variation2: SetNonNullable<{a: number; b: string | null | undefined}, 'b'>;
expectType<{a: number; b: string}>(variation2);

// Update an optional key.
declare const variation3: SetNonNullable<{a: number; b?: string | undefined}, 'b'>;
expectType<{a: number; b?: string}>(variation3);

// Fail if type changes even if non-nullable is right.
declare const variation4: SetNonNullable<{a: number; b: string | undefined}, 'b'>;
expectError<{a: string; b: string}>(variation4);

0 comments on commit 1a69e63

Please sign in to comment.