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

Rename Mutable to Writable #398

Merged
merged 1 commit into from
May 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 index.d.ts
Expand Up @@ -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';
Expand Down
2 changes: 1 addition & 1 deletion readme.md
Expand Up @@ -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<T>`.
- [`Writable`](source/writable.d.ts) - Create a type that strips `readonly` from all or some of an object's keys. The inverse of `Readonly<T>`. 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.
Expand Down
41 changes: 3 additions & 38 deletions 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<T>`.

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<Foo> = {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<Foo, 'b' | 'c'>;
// 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<BaseType, Keys extends keyof BaseType = keyof BaseType> =
Simplify<
// 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 by removing the `readonly` modifier from the key.
{-readonly [KeyType in keyof Pick<BaseType, Keys>]: Pick<BaseType, Keys>[KeyType]}
>;
Writable<BaseType, Keys>;
40 changes: 40 additions & 0 deletions 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<T>`.

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<Foo> = {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<Foo, 'b' | 'c'>;
// 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<BaseType, Keys extends keyof BaseType = keyof BaseType> =
Simplify<
// Pick just the keys that are not writable from the base type.
Except<BaseType, Keys> &
// 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<BaseType, Keys>]: Pick<BaseType, Keys>[KeyType]}
>;
28 changes: 0 additions & 28 deletions test-d/mutable.ts

This file was deleted.

28 changes: 28 additions & 0 deletions 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<Foo> = {a: 1, b: '2'};
ab.a = 2;
const ab2: Writable<Readonly<Foo>> = 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);