I'm trying to define a type that will allow me to "tag" members and static members of some type.
Assuming I have the following class
class testCase{
a='';
static b='';
}
I want my function to receive the class as the first parameter (I need it) and a second parameter of options that are optional (event the static is optional) as follows:
myFunc(testCase, {a:true,static:{b:true});
or
myFunc(testCase, {static:{b:true});
or
myFunc(testCase, {a:true);
I've played around with keyof, and couldn't get this to work. I can get keyof to work on the class or it's static - but not both:
I've tried:
export declare type Members<T, Y> = {
[Properties in keyof Partial<T>]: boolean
} & {
static?: {
[Properties in keyof Partial<Y>]: boolean
}
}
function myMembersFunction<T, Y extends { new(): T }>(c: Y, member: Members<T, Y>) {
}
But it doesn't work - and I'm not sure why
I've tried as a step on the way, creating the following function:
const members: keyof testCase = 'a';
const staticMembers: keyof typeof testCase = 'b';
function myFunction<T, Y extends { new(): T }>(c: Y, member: keyof T, staticMembers: keyof Y) {
console.log({ member, staticMembers });
}
myFunction(testCase, "a", "b");
But got an interesting case that I don't understand, saying that when the third parameter is wrong, it marks it as wrong - that's great , but if the second parameter is wrong, it marks the first parameter as wrong
CodePudding user response:
Here is the solution (you can see it in action here):
type Members<T> = T extends new(...args: any[]) => infer R ? { [K in keyof R]?: boolean } : never;
type StaticMembers<T> = { [K in keyof T]?: boolean };
function myFunc<T>(ctor: T, options: Members<T> & { static?: StaticMembers<T> }): void {
console.log(ctor, options);
}
Your basic idea was correct, it's just a little refinements. Most obvious is you don't need two arguments T
and Y
because they are basically the 1-to-1 thing which can be calculated from either of them.