I'm having trouble utilizing the solution provided in this response to exclude functions when invoking the set
method with class fields, as it results in the error message
Type instantiation is excessively deep and possibly infinite.
. I came across this inquiry, but using // @ts-ignore
isn't an option due to compromising type safety. The recommended approach in that post also doesn't seem applicable in my case. Additionally, I found this related discussion, but the implementation details are unclear to me, likely because of my limited understanding of TS recursive generics. How can I retrieve field properties recursively while excluding functions and considering whether the fields are optional or not, without encountering the excessively deep error?
Please note: there may be additional issues present in the linked code, so I'm hoping for assistance from a seasoned TypeScript expert to address them.
Access the Fiddle and review the following 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);