Currently I'm able to get a union of the key and values of each object literal passed into a function.
e.g.
interface StaticClass<T = any> {
new (...args: any[]): T
}
type RecordOfStaticClasses = Record<string, StaticClass>;
type RecordOfInstances<T extends RecordOfStaticClasses> = Record<keyof T, InstanceType<T[keyof T]>>;
const transformObjLiteral = <T extends RecordOfStaticClasses>(input: T): RecordOfInstances<T> => {
return Object.fromEntries(Object.entries(input).map(([key, value]) => [key, new value])) as RecordOfInstances<T>;
}
// Transformation
class Cat {
asleep: boolean;
}
class Zebra {
hoofLength: number;
}
transformObjLiteral({ myCat: Cat }).myCat.asleep // works if only 1 key is added
transformObjLiteral({ myCat: Cat, myZebra: Zebra }).myCat.asleep // Error: Property 'asleep' does not exist on type 'Cat | Zebra'!
As can be seen from above, it works well when only a object literal with 1 key is passed. However when adding two keys it cant get specific due to the possibility of a Union type. I know I can use Generics (e.g. transformObjLiteral<{ myCat: Cat }>({ myCat: Cat })
) but I hope to accomplish this implicitly based on the argument by itself. Is this posible?
CodePudding user response:
Instead of using a Record
, use a mapped type directly to keep the association between individual keys K
and their InstanceType<T[K]>
.
type RecordOfInstances<T extends RecordOfStaticClasses> = {
[K in keyof T]: InstanceType<T[K]>
}