Home > Net >  Why typescript complains that XXX is assignable to the constraint of type 'T', but 'T
Why typescript complains that XXX is assignable to the constraint of type 'T', but 'T

Time:12-17

My code is this:

export interface TreeItem {
  id: string;
  children: this[];
  collapsed?: boolean;
}

const createTreeItem = <T extends TreeItem>(): T => {
  return {
    id: 'root',
    children: []
  }
}

But I get an error on the return type of createTreeItem which is the following:

TS2322: Type '{ id: string; children: never[]; }' is not assignable to type 'T'.   '{ id: string; children: never[]; }' is assignable to the constraint of type 'T', but 'T' could be instantiated with a different subtype of constraint 'TreeItem'.

I have absolutely no idea what does this mean.

Any help ?

CodePudding user response:

So let's say you call your function as follows:

let node = createTreeItem<TreeItem>()

All good, right? The return type T is TreeItem, and the object your generic function is hardcoded to return does in fact have a type that qualifies it as a TreeItem:

{ id: string; children: never[]; }

But the point of giving your function a type parameter is to allow it to be called with other types of T, as long as they extend TreeItem. So the following should be a legal call:

export interface BidiTreeItem {
  id: string;
  children: this[];
  parent: this;
  collapsed?: boolean;
}

let node = createTreeItem<BidiTreeItem>()

The call is legal, since BidiTreeItem satisfies the constraint T extends TreeItem. The return type of this call, as declared in your function definition, is BidiTreeItem, but what your function returns is NOT a BidiTreeItem.

If you reread the error message again but with the above example in mind, it will now make sense to you. But just in case, below I will translate each piece of the error message. Note that the first sentence is the conclusion, so it will go last in this table:

this part of the error message... means this (using above example)...
'{ id: string; children: never[]; }' is assignable to the constraint of type 'T' '{ id: string; children: never[]; }' is consistent with the constraint T extends TreeItem
but 'T' could be instantiated with a different subtype of constraint 'TreeItem'. but T could be instantiated with a different subtype of TreeItem, for example BidiTreeItem.
TS2322: Type '{ id: string; children: never[]; }' is not assignable to type 'T'. The object your function is returning is not guaranteed to be assignable to type T, because T could be some other subtype such as BidiTreeItem .

CodePudding user response:

You can add "as T after the return" :

const createTreeItem = (): T => ({ id: 'root', children: [] } as T);

  • Related