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

Add Mutable type #157

Merged
merged 29 commits into from Dec 31, 2020
Merged
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
a29eb5b
Add `SetMutable` type
kainiedziela Nov 26, 2020
552c1e4
Add `SetMutable` to readme
kainiedziela Nov 26, 2020
9b41e0f
Update set-mutable.d.ts
kainiedziela Nov 26, 2020
906a629
Update readme.md
sindresorhus Nov 28, 2020
f8588ad
Update base.d.ts
sindresorhus Nov 28, 2020
8fd0d33
Remove default type arg and add additional docs
kainiedziela Nov 28, 2020
9590e53
Update set-mutable.d.ts
sindresorhus Dec 1, 2020
b350c30
Update mutable.d.ts
sindresorhus Dec 1, 2020
dfeff63
Clarify relationships
kainiedziela Dec 1, 2020
103c63f
Update source/set-mutable.d.ts
kainiedziela Dec 1, 2020
b5fde12
Update wrong comments
kainiedziela Dec 1, 2020
b7b495b
Update source/mutable.d.ts
kainiedziela Dec 1, 2020
02b440b
Update source/mutable.d.ts
kainiedziela Dec 1, 2020
1af6d4a
Use `Simplify` type for flattening `Set-` types output
kainiedziela Dec 2, 2020
8a41605
Mege `SetMutable` with `Mutable`
kainiedziela Dec 2, 2020
50f5447
Update simplify.d.ts
sindresorhus Dec 16, 2020
d953a14
Update mutable.d.ts
sindresorhus Dec 16, 2020
2a43c51
Remove obsolete test file
kainiedziela Dec 17, 2020
4de5143
Improve documentation
kainiedziela Dec 17, 2020
5d0986f
Merge branch 'set-mutable' of https://github.com/kainiedziela/type-fe…
kainiedziela Dec 17, 2020
f6edcd1
Update source/simplify.d.ts
kainiedziela Dec 17, 2020
c93f096
Update source/mutable.d.ts
kainiedziela Dec 17, 2020
def1d3f
Improve documentation
kainiedziela Dec 17, 2020
fb52746
Merge branch 'set-mutable' of https://github.com/kainiedziela/type-fe…
kainiedziela Dec 17, 2020
c8cc662
Update readme.md
kainiedziela Dec 20, 2020
87a78c7
Update mutable.d.ts
sindresorhus Dec 26, 2020
a8f42ad
Merge branch 'master' into set-mutable
sindresorhus Dec 26, 2020
55c60e2
Import utility types into Mutable
kainiedziela Dec 26, 2020
0db9d7f
Merge branch 'set-mutable' of https://github.com/kainiedziela/type-fe…
kainiedziela Dec 26, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions base.d.ts
Expand Up @@ -18,6 +18,7 @@ export {Promisable} from './source/promisable';
export {Opaque} from './source/opaque';
export {SetOptional} from './source/set-optional';
export {SetRequired} from './source/set-required';
export {SetMutable} from './source/set-mutable';
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 @@ -73,6 +73,7 @@ Click the type names for complete docs.
- [`Opaque`](source/opaque.d.ts) - Create an [opaque type](https://codemix.com/opaque-types-in-javascript/).
- [`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.
- [`SetMutable`](source/set-mutable.d.ts) - Create a type that converts the given keys from `readonly` to mutable.
- [`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.
- [`PromiseValue`](source/promise-value.d.ts) - Returns the type that is wrapped inside a `Promise`.
- [`AsyncReturnType`](source/async-return-type.d.ts) - Unwrap the return type of a function that returns a `Promise`.
Expand Down
8 changes: 6 additions & 2 deletions source/mutable.d.ts
Expand Up @@ -3,17 +3,21 @@ Convert an object with `readonly` keys into a mutable object. Inverse of `Readon

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), and [construct a `readonly` object within a function](https://github.com/Microsoft/TypeScript/issues/24509).

@see [`SetMutable`](source/set-mutable.d.ts) – a type that can selectively set some keys as mutable.

@example
```
import {Mutable} from 'type-fest';

type Foo = {
readonly a: number;
readonly b: string;
readonly b: readonly string[];
kainiedziela marked this conversation as resolved.
Show resolved Hide resolved
kainiedziela marked this conversation as resolved.
Show resolved Hide resolved
};

const mutableFoo: Mutable<Foo> = {a: 1, b: '2'};
const mutableFoo: Mutable<Foo> = {a: 1, b: ['2']};
mutableFoo.a = 3;
mutableFoo.b[0] = '3'; //=> Index signature in type 'readonly string[]' only permits reading.ts(2542).
mutableFoo.b = ['3'];
```
*/
export type Mutable<ObjectType> = {
Expand Down
37 changes: 37 additions & 0 deletions source/set-mutable.d.ts
@@ -0,0 +1,37 @@
import {Except} from './except';
import {Mutable} from './mutable';

/**
Create a type that converts the given keys from `readonly` to mutable. The remaining keys are kept as is.

kainiedziela marked this conversation as resolved.
Show resolved Hide resolved
Use-case: You want to define a single model where the only thing that changes is whether or not some of the keys are mutable.

kainiedziela marked this conversation as resolved.
Show resolved Hide resolved
@see [`Mutable`](source/mutable.d.ts) - a type that sets all (not selectively) keys as mutable.

@example
```
import {SetMutable} from 'type-fest';

type Foo = {
readonly a: number;
b: readonly string[];
readonly c: boolean;
}

type SomeMutable = SetMutable<Foo, 'b' | 'c'>;
// type SomeMutable = {
// readonly a: number;
// b: readonly string[]; // Was already mutable and still is, type of the property remains unaffected.
// c: boolean; // Is now mutable.
// }
```
*/
export type SetMutable<BaseType, Keys extends keyof BaseType> =
kainiedziela marked this conversation as resolved.
Show resolved Hide resolved
// Pick just the keys that are not mutable from the base type.
Except<BaseType, Keys> &
// Pick the keys that should be mutable from the base type and make them mutable.
Mutable<Pick<BaseType, Keys>> extends
// If `InferredType` extends the previous, then for each key, use the inferred type key.
kainiedziela marked this conversation as resolved.
Show resolved Hide resolved
infer InferredType
? {[KeyType in keyof InferredType]: InferredType[KeyType]}
kainiedziela marked this conversation as resolved.
Show resolved Hide resolved
: never;
2 changes: 1 addition & 1 deletion source/set-optional.d.ts
Expand Up @@ -23,7 +23,7 @@ type SomeOptional = SetOptional<Foo, 'b' | 'c'>;
// }
```
*/
export type SetOptional<BaseType, Keys extends keyof BaseType = keyof BaseType> =
export type SetOptional<BaseType, Keys extends keyof BaseType> =
// Pick just the keys that are not optional from the base type.
Except<BaseType, Keys> &
// Pick the keys that should be optional from the base type and make them optional.
Expand Down
2 changes: 1 addition & 1 deletion source/set-required.d.ts
Expand Up @@ -23,7 +23,7 @@ type SomeRequired = SetRequired<Foo, 'b' | 'c'>;
// }
```
*/
export type SetRequired<BaseType, Keys extends keyof BaseType = keyof BaseType> =
export type SetRequired<BaseType, Keys extends keyof BaseType> =
// Pick just the keys that are not required from the base type.
Except<BaseType, Keys> &
// Pick the keys that should be required from the base type and make them required.
Expand Down
18 changes: 18 additions & 0 deletions test-d/set-mutable.ts
@@ -0,0 +1,18 @@
import {expectType, expectError} from 'tsd';
kainiedziela marked this conversation as resolved.
Show resolved Hide resolved
import {SetMutable} from '..';

// Update one required and one optional to required.
declare const variation1: SetMutable<{readonly a: number; b: string; readonly c: boolean}, 'b' | 'c'>;
expectType<{readonly a: number; b: string; c: boolean}>(variation1);

// Update two optional to required.
declare const variation2: SetMutable<{readonly a: number; readonly b: string; readonly c: boolean}, 'a' | 'b'>;
expectType<{a: number; b: string; readonly c: boolean}>(variation2);

// Three required remain required.
declare const variation3: SetMutable<{a: number; b: string; c: boolean}, 'a' | 'b' | 'c'>;
expectType<{a: number; b: string; c: boolean}>(variation3);

// Fail if type changes even if optional is right.
declare const variation4: SetMutable<{readonly a: number; b: string; readonly c: boolean}, 'b' | 'c'>;
expectError<{readonly a: boolean; b: string; c: boolean}>(variation4);
kainiedziela marked this conversation as resolved.
Show resolved Hide resolved