diff --git a/index.d.ts b/index.d.ts index e7f91523d..27f1b8294 100644 --- a/index.d.ts +++ b/index.d.ts @@ -7,6 +7,7 @@ export * from './source/observable-like'; // Utilities export {Except} from './source/except'; export {Mutable} from './source/mutable'; +export {Writable} from './source/writable'; export {Merge} from './source/merge'; export {MergeExclusive} from './source/merge-exclusive'; export {RequireAtLeastOne} from './source/require-at-least-one'; diff --git a/readme.md b/readme.md index 693422867..1d7e95e9c 100644 --- a/readme.md +++ b/readme.md @@ -161,7 +161,7 @@ Click the type names for complete docs. ### Utilities - [`Except`](source/except.d.ts) - Create a type from an object type without certain keys. This is a stricter version of [`Omit`](https://www.typescriptlang.org/docs/handbook/utility-types.html#omittype-keys). -- [`Mutable`](source/mutable.d.ts) - Create a type that strips `readonly` from all or some of an object's keys. The inverse of `Readonly`. +- [`Writable`](source/writable.d.ts) - Create a type that strips `readonly` from all or some of an object's keys. The inverse of `Readonly`. Formerly named `Mutable`. - [`Merge`](source/merge.d.ts) - Merge two types into a new type. Keys of the second type overrides keys of the first type. - [`MergeExclusive`](source/merge-exclusive.d.ts) - Create a type that has mutually exclusive keys. - [`RequireAtLeastOne`](source/require-at-least-one.d.ts) - Create a type that requires at least one of the given keys. diff --git a/source/mutable.d.ts b/source/mutable.d.ts index 40b509137..9568fbd4c 100644 --- a/source/mutable.d.ts +++ b/source/mutable.d.ts @@ -1,40 +1,5 @@ -import type {Except} from './except'; -import type {Simplify} from './simplify'; +import type {Writable} from './writable'; -/** -Create a type that strips `readonly` from all or some of an object's keys. Inverse of `Readonly`. - -This can be used to [store and mutate options within a class](https://github.com/sindresorhus/pageres/blob/4a5d05fca19a5fbd2f53842cbf3eb7b1b63bddd2/source/index.ts#L72), [edit `readonly` objects within tests](https://stackoverflow.com/questions/50703834), [construct a `readonly` object within a function](https://github.com/Microsoft/TypeScript/issues/24509), or to define a single model where the only thing that changes is whether or not some of the keys are mutable. - -@example -``` -import type {Mutable} from 'type-fest'; - -type Foo = { - readonly a: number; - readonly b: readonly string[]; // To show that only the mutability status of the properties, not their values, are affected. - readonly c: boolean; -}; - -const mutableFoo: Mutable = {a: 1, b: ['2'], c: true}; -mutableFoo.a = 3; -mutableFoo.b[0] = 'new value'; // Will still fail as the value of property "b" is still a readonly type. -mutableFoo.b = ['something']; // Will work as the "b" property itself is no longer readonly. - -type SomeMutable = Mutable; -// type SomeMutable = { -// readonly a: number; -// b: readonly string[]; // It's now mutable. The type of the property remains unaffected. -// c: boolean; // It's now mutable. -// } -``` - -@category Object -*/ +/** @deprecated @see Writable */ export type Mutable = - Simplify< - // Pick just the keys that are not mutable from the base type. - Except & - // Pick the keys that should be mutable from the base type and make them mutable by removing the `readonly` modifier from the key. - {-readonly [KeyType in keyof Pick]: Pick[KeyType]} - >; + Writable; diff --git a/source/writable.d.ts b/source/writable.d.ts new file mode 100644 index 000000000..5bb717ad6 --- /dev/null +++ b/source/writable.d.ts @@ -0,0 +1,40 @@ +import type {Except} from './except'; +import type {Simplify} from './simplify'; + +/** +Create a type that strips `readonly` from all or some of an object's keys. Inverse of `Readonly`. + +This can be used to [store and mutate options within a class](https://github.com/sindresorhus/pageres/blob/4a5d05fca19a5fbd2f53842cbf3eb7b1b63bddd2/source/index.ts#L72), [edit `readonly` objects within tests](https://stackoverflow.com/questions/50703834), [construct a `readonly` object within a function](https://github.com/Microsoft/TypeScript/issues/24509), or to define a single model where the only thing that changes is whether or not some of the keys are writable. + +@example +``` +import type {Writable} from 'type-fest'; + +type Foo = { + readonly a: number; + readonly b: readonly string[]; // To show that only the mutability status of the properties, not their values, are affected. + readonly c: boolean; +}; + +const writableFoo: Writable = {a: 1, b: ['2'], c: true}; +writableFoo.a = 3; +writableFoo.b[0] = 'new value'; // Will still fail as the value of property "b" is still a readonly type. +writableFoo.b = ['something']; // Will work as the "b" property itself is no longer readonly. + +type SomeWritable = Writable; +// type SomeWritable = { +// readonly a: number; +// b: readonly string[]; // It's now writable. The type of the property remains unaffected. +// c: boolean; // It's now writable. +// } +``` + +@category Object +*/ +export type Writable = + Simplify< + // Pick just the keys that are not writable from the base type. + Except & + // Pick the keys that should be writable from the base type and make them writable by removing the `readonly` modifier from the key. + {-readonly [KeyType in keyof Pick]: Pick[KeyType]} + >; diff --git a/test-d/mutable.ts b/test-d/mutable.ts deleted file mode 100644 index 9eb23f511..000000000 --- a/test-d/mutable.ts +++ /dev/null @@ -1,28 +0,0 @@ -import {expectType, expectError} from 'tsd'; -import type {Mutable} from '../index'; - -type Foo = { - readonly a: number; - readonly b: string; -}; - -const ab: Mutable = {a: 1, b: '2'}; -ab.a = 2; -const ab2: Mutable> = ab; -ab2.a = 2; - -// Update one mutable and one readonly to mutable, leaving one property unaffected. -declare const variation1: Mutable<{readonly a: number; b: string; readonly c: boolean}, 'b' | 'c'>; -expectType<{readonly a: number; b: string; c: boolean}>(variation1); - -// Update two readonly to mutable, leaving one property unaffected. -declare const variation2: Mutable<{readonly a: number; readonly b: string; readonly c: boolean}, 'a' | 'b'>; -expectType<{a: number; b: string; readonly c: boolean}>(variation2); - -// Three mutable remain mutable. -declare const variation3: Mutable<{a: number; b: string; c: boolean}, 'a' | 'b' | 'c'>; -expectType<{a: number; b: string; c: boolean}>(variation3); - -// Check if type changes raise an error even if readonly and mutable are applied correctly. -declare const variation4: Mutable<{readonly a: number; b: string; readonly c: boolean}, 'b' | 'c'>; -expectError<{readonly a: boolean; b: string; c: boolean}>(variation4); diff --git a/test-d/writable.ts b/test-d/writable.ts new file mode 100644 index 000000000..d69c0f2b8 --- /dev/null +++ b/test-d/writable.ts @@ -0,0 +1,28 @@ +import {expectType, expectError} from 'tsd'; +import type {Writable} from '../index'; + +type Foo = { + readonly a: number; + readonly b: string; +}; + +const ab: Writable = {a: 1, b: '2'}; +ab.a = 2; +const ab2: Writable> = ab; +ab2.a = 2; + +// Update one writable and one readonly to writable, leaving one property unaffected. +declare const variation1: Writable<{readonly a: number; b: string; readonly c: boolean}, 'b' | 'c'>; +expectType<{readonly a: number; b: string; c: boolean}>(variation1); + +// Update two readonly to writable, leaving one property unaffected. +declare const variation2: Writable<{readonly a: number; readonly b: string; readonly c: boolean}, 'a' | 'b'>; +expectType<{a: number; b: string; readonly c: boolean}>(variation2); + +// Three writable remain writable. +declare const variation3: Writable<{a: number; b: string; c: boolean}, 'a' | 'b' | 'c'>; +expectType<{a: number; b: string; c: boolean}>(variation3); + +// Check if type changes raise an error even if readonly and writable are applied correctly. +declare const variation4: Writable<{readonly a: number; b: string; readonly c: boolean}, 'b' | 'c'>; +expectError<{readonly a: boolean; b: string; c: boolean}>(variation4);