I have following four types
Type T1
export type T1 = "p" | "q" | "r" | "a" | "b";
Type T2
export type T2 = {
h: string;
hc: {};
};
Interface Def
export interface Def {
[k: string]: {
[K in T1 | "abc"]?: K extends T1
? T2
: {
[k in T1]?: T2;
};
};
}
Interface A
export interface A {
name: string;
def: Def;
}
The usage should be like follows
const x: A = {
name: "test",
def: {
xxx: {
p: {
h: "s",
hc: {
},
},
abc: {
p: {
h: "s",
hc: {
},
},
abc: {
p: {
h: "s",
hc: {
},
},
},
},
},
},
};
The problem I am having is that if the object of type Def with in attribute xxx has property abc then it should recursively accept the abc object again as above example. I tried calling Def
recursively but that does not work.
I would suggest writing Def
like
interface Def {
[k: string]: DefEntry
}
where DefEntry
is a recursive object type:
type DefEntry =
{ [K in T1]?: T2 } & // this is equivalent to Partial<Record<T1, T2>>
{ abc?: DefEntry };
or, equivalently, you could write DefEntry
as a recursive interface like
interface DefEntry extends Partial<Record<T1, T2>> {
abc?: DefEntry
}
In neither case is conditional types like K extends T1 ? T2 : ...
necessary.
And that makes your A
interface and the test value work as desired:
const x: A = { // okay
name: "test",
def: {
xxx: {
p: { h: "s", hc: {}, },
abc: {
p: { h: "s", hc: {}, },
abc: {
p: { h: "s", hc: {}, },
},
},
},
},
};