I'm trying to build a type that is recursively reading an array of types to build a template literal. Hard to explain, but this is a very simple code to explain what I'm looking for can be find in TS PLAYGROUND
The type RECUR has 2 arguments : the parent class and an optional array CHILDS of other classes extending CBaseClass.
If this array is not set, the problem fields can only accept properties from the parent class. This is working
If the array is not empty, populated by classes that extends the CBaseClass, problem can contains any of the key of the parent class as well as any key of the Class in the Generic Array. Unfortunalty, I don't know how to do this. I "forced" the keys of Child[0], but this is obviously wrong.
Test cases (based on the example below)
case 1: only the parent class is set in the generics and the array of CBaseClass is not set
Result : only the keys of CParent can be chosen for problem field
const case1ArrayIsEmpty:RECUR<CParent> = {
stupid : new CParent(),
problem:["id", "child1", "child2"] <-- only keys of CPARENT can be here
}
case 2: the parent class is set in the generics and the array of CBaseClass contains CCHild1 or Child2
Result : the keys of CParent can be chosen for problem field, and if one key is of Class CBaseClass, the path of keys toCChild1 or CChild2 can be proposed.
const case2WithChild1:RECUR<CParent, CChild1> = {
stupid : new CParent(),
problem:["id", "child1", "child2", "child1.idChild1", "child1.SubChild11"] <-- keys of CPARENT, CChild1 can be here
}
const case2WithChild2:RECUR<CParent, CChild2> = {
stupid : new CParent(),
problem:["id", "child1", "child2", "child2.idChild2", "child2.foo"] <-- keys of CPARENT, CChild2 can be here
}
case 3: Both CChild1 and Child2 are in the array. In fact the result is a merge of case 2 with child1 and child
problem:["id", "child1", "child1.idChild1", "child1.SubChild11", "child2", "child2.idChild2", "child2.foo"]
case 4 {the worst} : if CChild1 is in the array, then CSubChild1 can be in the array, and its keys can be in problem field
the recusion is here, but don't know how to do t
const case4WithChild1Child2AndSubChild1:RECUR<CParent,CChild1, CChild2, CSubChild1> <-- CSubChild1 can be chosen because CCHild1 is already in array and CSubChild1 is of class CBaseClass
= {
stupid : new CParent(),
problem:[
"id",
"child1",
"child1".subChild1,
"child1.subChild1.idsubChild1",
"child1.subChild1.bar",
"child2",
"child2.idChild2",
"child2.foo"
]
}
SET OF DATA TO TEST
class CBaseClass {
static value: number;
}
class CParent extends CBaseClass {
id: string;
child1: CChild1;
child2: CChild2;
}
class CChild1 extends CBaseClass {
idChild1: string;
Subchild11: CSubChild1;
}
class CChild2 extends CBaseClass {
idChild2: string;
foo: number;
}
class CSubChild1 extends CBaseClass {
idSubChild1: string;
bar: string;
}
type RECUR<TClass extends CBaseClass, Childs extends Array<CBaseClass> | never = never> = {
stupid:TClass,
problem:Array<keyof TClass | (Childs extends Array<CBaseClass>?`${string & keyof TClass}.${string & keyof Childs[0]}`:never)> // <-- this is wrong but how can do recursive ?
}
const work:RECUR<CParent> = {
stupid : new CParent(),
problem:["id", "child1"]
}
console.log(work)
const doesntwork:RECUR<CParent, [CChild1, CChild2, CSubChild1 ]> = {
stupid : new CParent(),
problem:["id", "child1", ""]
}
