UNPKG

3.28 kBTypeScriptView Raw
1import type {BuiltIns, HasMultipleCallSignatures} from './internal';
2
3/**
4Create a deeply mutable version of an `object`/`ReadonlyMap`/`ReadonlySet`/`ReadonlyArray` type. The inverse of `ReadonlyDeep<T>`. Use `Writable<T>` if you only need one level deep.
5
6This 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.
7
8@example
9```
10import type {WritableDeep} from 'type-fest';
11
12type Foo = {
13 readonly a: number;
14 readonly b: readonly string[]; // To show that mutability is deeply affected.
15 readonly c: boolean;
16};
17
18const writableDeepFoo: WritableDeep<Foo> = {a: 1, b: ['2'], c: true};
19writableDeepFoo.a = 3;
20writableDeepFoo.b[0] = 'new value';
21writableDeepFoo.b = ['something'];
22```
23
24Note that types containing overloaded functions are not made deeply writable due to a [TypeScript limitation](https://github.com/microsoft/TypeScript/issues/29732).
25
26@see Writable
27@category Object
28@category Array
29@category Set
30@category Map
31*/
32export type WritableDeep<T> = T extends BuiltIns
33 ? T
34 : T extends (...arguments_: any[]) => unknown
35 ? {} extends WritableObjectDeep<T>
36 ? T
37 : HasMultipleCallSignatures<T> extends true
38 ? T
39 : ((...arguments_: Parameters<T>) => ReturnType<T>) & WritableObjectDeep<T>
40 : T extends ReadonlyMap<unknown, unknown>
41 ? WritableMapDeep<T>
42 : T extends ReadonlySet<unknown>
43 ? WritableSetDeep<T>
44 : T extends readonly unknown[]
45 ? WritableArrayDeep<T>
46 : T extends object
47 ? WritableObjectDeep<T>
48 : unknown;
49
50/**
51Same as `WritableDeep`, but accepts only `Map`s as inputs. Internal helper for `WritableDeep`.
52*/
53type WritableMapDeep<MapType extends ReadonlyMap<unknown, unknown>> =
54 MapType extends ReadonlyMap<infer KeyType, infer ValueType>
55 ? Map<WritableDeep<KeyType>, WritableDeep<ValueType>>
56 : MapType; // Should not heppen
57
58/**
59Same as `WritableDeep`, but accepts only `Set`s as inputs. Internal helper for `WritableDeep`.
60*/
61type WritableSetDeep<SetType extends ReadonlySet<unknown>> =
62 SetType extends ReadonlySet<infer ItemType>
63 ? Set<WritableDeep<ItemType>>
64 : SetType; // Should not heppen
65
66/**
67Same as `WritableDeep`, but accepts only `object`s as inputs. Internal helper for `WritableDeep`.
68*/
69type WritableObjectDeep<ObjectType extends object> = {
70 -readonly [KeyType in keyof ObjectType]: WritableDeep<ObjectType[KeyType]>
71};
72
73/**
74Same as `WritableDeep`, but accepts only `Array`s as inputs. Internal helper for `WritableDeep`.
75*/
76type WritableArrayDeep<ArrayType extends readonly unknown[]> =
77 ArrayType extends readonly [] ? []
78 : ArrayType extends readonly [...infer U, infer V] ? [...WritableArrayDeep<U>, WritableDeep<V>]
79 : ArrayType extends readonly [infer U, ...infer V] ? [WritableDeep<U>, ...WritableArrayDeep<V>]
80 : ArrayType extends ReadonlyArray<infer U> ? Array<WritableDeep<U>>
81 : ArrayType extends Array<infer U> ? Array<WritableDeep<U>>
82 : ArrayType;
83
84
\No newline at end of file