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);