I have no clues on how to solve this problem.
At the moment, I have this recursive interface definition as base for a generic tree structure:
interface TreeNodeBase<TNode extends TreeNodeBase<TNode, TData>, TData> {
readonly id: string;
readonly data: TData;
readonly children?: ReadonlyArray<TNode>;
}
To specialize a particular tree structure, I write something like this:
type MyTreeNode = TreeNodeBase<MyTreeNode, MyTreeNodeData>;
type MyTreeNodeData = string | number;
Note: I must use an interface, because the circular reference in the specialization (MyTreeNode
).
All that works like a charm.
Now, my goal is to make the "id" field configurable, because sometimes that field should better name "nodeId" or whatever string. In other words, I'd like to rewrite my original structure as:
interface TreeNodeBase<TNode extends TreeNodeBase<TNode, TData, TKey>, TData, TKey extends string = "id"> {
readonly id: string; //how to adjust this field???
readonly data: TData;
readonly children?: ReadonlyArray<TNode>;
}
However, I couldn't figure out the solution, if does exist.
I tried to leverage the mapped types, but unfortunately that won't apply to interfaces:
type TreeNodeKey<TKey extends string ="id"> = {
readonly [P in TKey]: string;
}
interface TreeNodeBase2<TNode extends TreeNodeBase2<TNode, TData, TKey>, TData, TKey extends string> extends TreeNodeKey<TKey> {
readonly data: TData;
readonly children?: ReadonlyArray<TNode>;
}
Is there any solution?
If you remove the recursion from the generic params you could use types:
type TreeNodeBase<TData, TNode extends object = {} /* allows add extra props to a node */, TKey extends string = "id", > = TNode & {
readonly data: TData;
readonly children?: ReadonlyArray<TreeNodeBase<TData, TNode, TKey>>;
} & {readonly [K in TKey]: string}
type BooleanTree1 = TreeNodeBase<boolean, {prop1: boolean}>;
type BooleanTree2 = TreeNodeBase<boolean, {prop2: boolean}>;
const booleanTree1: BooleanTree1 = {
id: 'id2',
data: true,
prop1: true,
children: [{
id: 'id2',
data: false,
prop2: true // error
}]
}