I'm trying to use this answer to exclude functions from when I call the set
method with essentially the fields of the class, but I get the error Type instantiation is excessively deep and possibly infinite.
I saw this question, but I can't use // @ts-ignore
because I'll lose my type safety, and the accepted answer modifies it in such a way that I don't know how to apply in my example. I also saw this question, but once again, it's a little confusing how to apply here, probably due to my lack of understanding TS recursive generics. How do I recursively retrieve the field properties (while excluding functions and respecting if the fields are optional or not) and not get the excessively deep error?
Note: there might be some additional issues in the linked code, so I'm wishing for a seasoned TS expert to fix them.
Fiddle and code:
// types taken from https://stackoverflow.com/a/62362197/1253609
type IfEquals<X, Y, A=X, B=never> =
(<T>() => T extends X ? 1 : 2) extends
(<T>() => T extends Y ? 1 : 2) ? A : B;
type WritableKeys<T> = {
[P in keyof T]: T[P] extends Function ? never : IfEquals<{ [Q in P]: T[P] }, { -readonly [Q in P]: T[P] }, P>
}[keyof T];
type DeepWritablePrimitive = undefined | null | boolean | string | number | Function;
type DeepWritable<T> =
T extends DeepWritablePrimitive ? T :
T extends Array<infer U> ? DeepWritableArray<U> :
T extends Map<infer K, infer V> ? DeepWritableMap<K, V> :
T extends Set<infer T> ? DeepWriableSet<T> : DeepWritableObject<T>;
type DeepWritableArray<T> = Array<DeepWritable<T>>;
type DeepWritableMap<K, V> = Map<K, DeepWritable<V>>;
type DeepWriableSet<T> = Set<DeepWritable<T>>;
type DeepWritableObject<T> = {
[K in WritableKeys<T>]: DeepWritable<T[K]>
};
class Base {
set(data?: Partial<DeepWritable<typeof this>>) {
Object.assign(this, data);
}
}
class Parent extends Base {
name?: string;
arr?: Parent[];
};
const record = new Parent();
record.set({
// https://github.com/microsoft/TypeScript/issues/34933
arr: [{
name: '0'
}]
})
console.log(record.arr);