Iggdrazil
Iggdrazil

Reputation: 55

Error 2344 Typescript when tryng to write a generic node element

I am currently trying to write a generic class in typescript which allows me to create a tree node with :

Unfortunately, my code seems wrong to typescript but I can't understand why?

I read several explanations about error 2344 but I am unable to make my code work the way I want.

Here is the error message :

Type 'GenericItem<Child, ItemData, Parent>' does not satisfy the constraint 'GenericItem<GenericItem<any, any, GenericItem<Child, ItemData, Parent>>, any, any>'.
  Types of property 'observer' are incompatible.
    Type '((children: Child[]) => void) | undefined' is not assignable to type '((children: GenericItem<any, any, GenericItem<Child, ItemData, Parent>>[]) => void) | undefined'.
      Type '(children: Child[]) => void' is not assignable to type '(children: GenericItem<any, any, GenericItem<Child, ItemData, Parent>>[]) => void'.
        Types of parameters 'children' and 'children' are incompatible.
          Type 'GenericItem<any, any, GenericItem<Child, ItemData, Parent>>[]' is not assignable to type 'Child[]'.
            Type 'GenericItem<any, any, GenericItem<Child, ItemData, Parent>>' is not assignable to type 'Child'.
              'GenericItem<any, any, GenericItem<Child, ItemData, Parent>>' is assignable to the constraint of type 'Child', but 'Child' could be instantiated with a different subtype of constraint 'GenericItem<any, any, GenericItem<Child, ItemData, Parent>>'.ts(2344)

Here is my code :

class GenericItem<
    Child extends GenericItem<any, any, GenericItem<Child, ItemData, Parent>>,
    ItemData, 
    Parent extends GenericItem<GenericItem<Child,ItemData,Parent>, any, any>
>{
    key : number
    children : Child[]
    data : ItemData
    observer ?: (children : Child[]) => void
    propsObserver ?: (props: ItemData) => void
    parent ?: Parent

    constructor(key: number, children : Child[] = [], data : ItemData){
        // key to prevent react component to rebuild from statch
        this.key = key
        // fieldsets in the current page (taken from props or empty by default)
        children.forEach( child => child.parent = this)
        this.children = children || []
        // props of the current page
        this.data = data
    }
}

Upvotes: 0

Views: 976

Answers (1)

Nenad
Nenad

Reputation: 26657

The GenericItem<> class seems overcomplicated.

You have issue of circular dependency there. Parent is defined as:

Parent extends GenericItem<GenericItem<Child,ItemData,Parent>, any, any>

However, in Child definition:

Child extends GenericItem<any, any, GenericItem<Child, ItemData, Parent>>

3rd type - GenericItem<Child, ItemData, Parent> is supposed to be Parent. The problem is that GenericItem<Child, ItemData, Parent> is not compatible with GenericItem<GenericItem<Child,ItemData,Parent>, any, any> that is defined in Parent extend...

Also, I am not sure how would you use such interface in your implementation (for example filling 2 levels of children items).

Upvotes: 1

Related Questions