type PrimitiveType = number | string | boolean; /** Object types that should never be mapped */ type AtomicObject = Function | Promise | Date | RegExp; /** * If the lib "ES2015.Collection" is not included in tsconfig.json, * types like ReadonlyArray, WeakMap etc. fall back to `any` (specified nowhere) * or `{}` (from the node types), in both cases entering an infinite recursion in * pattern matching type mappings * This type can be used to cast these types to `void` in these cases. */ type IfAvailable = true | false extends (T extends never ? true : false) ? Fallback : keyof T extends never ? Fallback : T; /** * These should also never be mapped but must be tested after regular Map and * Set */ type WeakReferences = IfAvailable> | IfAvailable>; type WritableDraft = { -readonly [K in keyof T]: Draft; }; /** Convert a readonly type into a mutable type, if possible */ type Draft = T extends PrimitiveType ? T : T extends AtomicObject ? T : T extends ReadonlyMap ? Map, Draft> : T extends ReadonlySet ? Set> : T extends WeakReferences ? T : T extends object ? WritableDraft : T; export type { WritableDraft as W };