import { NamedTypeDefinitionDeferred } from './reflection-type'; import { ShapeOf } from './runtime'; function asPlainObject(value: any): any { if (Array.isArray(value)) { return value.map(asPlainObject) as any; } if (value && typeof value === 'object') { return Object.keys(value).reduce((memo, key) => { (memo as any)[key] = asPlainObject(value[key]); return memo as any; }, {}); } return value; } export class ValueClass { public static reflection: NamedTypeDefinitionDeferred; } type WritableArray = Array>; type Fun = (...a: any[]) => any; type WritableObject = { -readonly [P in keyof T]: Writable }; export type Writable = T extends ReadonlyArray ? WritableArray : T extends Fun ? T : T extends object ? WritableObject : T; export function toJSON(value: Cls): Cls extends ValueClass ? Writable> : never { return toShape(value) as any; } export function toShape(value: Cls): Cls extends ValueClass ? ShapeOf : never { // we cant use _.cloneDeep as that copies the instance allowing a surprising way to // create proof carrying objects that do not respect the class constraints return asPlainObject(value as any); // how to say that 'this' is the extending class }