-
-
Notifications
You must be signed in to change notification settings - Fork 546
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9c148ac
commit b2e22fb
Showing
4 changed files
with
58 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import type {Except} from './except'; | ||
import type {Simplify} from './simplify'; | ||
|
||
/** | ||
Create a type that makes the given keys readonly. 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 readonly. | ||
@example | ||
``` | ||
import type {SetReadonly} from 'type-fest'; | ||
type Foo = { | ||
a: number; | ||
readonly b: string; | ||
c: boolean; | ||
} | ||
type SomeReadonly = SetReadonly<Foo, 'b' | 'c'>; | ||
// type SomeReadonly = { | ||
// a: number; | ||
// readonly b: string; // Was already readonly and still is. | ||
// readonly c: boolean; // Is now readonly. | ||
// } | ||
``` | ||
@category Object | ||
*/ | ||
export type SetReadonly<BaseType, Keys extends keyof BaseType> = | ||
// `extends unknown` is always going to be the case and is used to convert any | ||
// union into a [distributive conditional | ||
// type](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#distributive-conditional-types). | ||
BaseType extends unknown | ||
? Simplify< | ||
Except<BaseType, Keys> & | ||
Readonly<Pick<BaseType, Keys>> | ||
> | ||
: never; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
import {expectNotAssignable, expectType} from 'tsd'; | ||
import type {SetReadonly} from '../index'; | ||
|
||
// Update one readonly and one non readonly to readonly. | ||
declare const variation1: SetReadonly<{a: number; readonly b: string; c: boolean}, 'b' | 'c'>; | ||
expectType<{a: number; readonly b: string; readonly c: boolean}>(variation1); | ||
|
||
// Update two non readonly to readonly. | ||
declare const variation2: SetReadonly<{readonly a: number; readonly b: string; c: boolean}, 'a' | 'b'>; | ||
expectType<{readonly a: number; readonly b: string; c: boolean}>(variation2); | ||
|
||
// Three readonly remain readonly. | ||
declare const variation3: SetReadonly<{readonly a: number; readonly b?: string; readonly c: boolean}, 'a' | 'b' | 'c'>; | ||
expectType<{readonly a: number; readonly b?: string; readonly c: boolean}>(variation3); | ||
|
||
// Fail if type changes even if readonly is right. | ||
declare const variation4: SetReadonly<{a: number; readonly b: string; c: boolean}, 'b' | 'c'>; | ||
expectNotAssignable<{a: boolean; readonly b: string; readonly c: boolean}>(variation4); |