I have to do an exercise with data structures, specifically with a doubly linked list and I don't understand why when I try to add two objects to the list I get this error:
"Argument of type '{ id_user: number; id_touristic_place: number; review_title: string; review_desc: string; review_points: number; }' is not assignable to parameter of type 'T'. 'T' could be instantiated with an arbitrary type which could be unrelated to '{ id_user: number; id_touristic_place: number; review_title: string; review_desc: string; review_points: number; }'.ts(2345)"
I Tried this from the documentation of TS
public addAtEnd<T>(data: T): void
but that give me another error related to the node
I would appreciate it if you could try to explain to me the reason for the error. (I'm new on TS)
Here is my code:
export class Node<T> {
public data: T;
public next: Node<T> | null;
public prev: Node<T> | null;
constructor(data: T) {
this.data = data;
this.next = null;
this.prev = null;
}
}
import { Node } from "./Node";
import { ILinkedList } from "./ILinkedList";
export class LinkedList<T> implements ILinkedList<T> {
private head: Node<T> | null;
constructor() {
this.head = null;
}
public get gethead(): Node<T> | null {
return this.head;
}
public set sethead(head: Node<T>) {
this.head = head;
}
public addAtEnd(data: T): void {
const newNode = new Node(data);
if (!this.head) {
this.head = newNode;
} else {
const getLast = (node: Node<T>): Node<T> => {
return node.next ? getLast(node.next) : node;
};
const lastNode = getLast(this.head);
newNode.prev = lastNode;
lastNode.next = newNode;
}
}
public addTwo(): void {
this.addAtEnd({
id_user: 1,
id_touristic_place: 11,
review_title: "Nice place",
review_desc: "C:",
review_points: 0,
});
this.addAtEnd({
id_user: 2,
id_touristic_place: 11,
review_title: "Good",
review_desc: "Not bad at all ",
review_points: 0,
});
}
}
Your LinkedList class is generic, which means that you can't assume it holds any specific type of data.
If you want to store a type of data in a list e.g. Users, you need to specify that type. This is typically done by constructing an instance of LinkedList<User>.
You could also create a class ListOfUsers extends LinkedList<User> but this would only be useful if there is functionality that applies to a list of users but doesn't apply to lists of any other data type.
For example:
export class LinkedList<T> implements ILinkedList<T> {
private head: Node<T> | null;
constructor() {
this.head = null;
}
public get gethead(): Node<T> | null {
return this.head;
}
public set sethead(head: Node<T>) {
this.head = head;
}
public addAtEnd(data: T): void {
const newNode = new Node(data);
if (!this.head) {
this.head = newNode;
} else {
const getLast = (node: Node<T>): Node<T> => {
return node.next ? getLast(node.next) : node;
};
const lastNode = getLast(this.head);
newNode.prev = lastNode;
lastNode.next = newNode;
}
}
}
interface User {
id_user: number;
id_touristic_place: number;
review_title: string;
review_desc: string;
review_points: number;
};
const myList = new LinkedList<User>();
myList.addAtEnd({
id_user: 1,
id_touristic_place: 11,
review_title: "Nice place",
review_desc: "C:",
review_points: 0,
});
myList.addAtEnd({
id_user: 2,
id_touristic_place: 11,
review_title: "Good",
review_desc: "Not bad at all ",
review_points: 0,
});
It's telling you that the object you're passing in on this line cannot possibly satisfy every possible type T.
this.addAtEnd({
id_user: 1,
id_touristic_place: 11,
review_title: "Nice place",
review_desc: "C:",
review_points: 0,
});
As one of the infinite possibilities, if T is number, then it would only be legal to pass in a number (as in this.addAtEnd(4)), but your code doesn't pass in a number.
The purpose of a generic is that your code works with any type, and as a result you can't make any assumptions about that type, unless you add restrictions to it. For your addTwo function, you're not going to be able to create an ad-hoc object which matches every possible T, so about the only practical thing you could do is have it accept the data as arguments. With that, whoever's using this class can supply data of the type that they have in mind.
public addTwo(first: T, second: T): void {
this.addAtEnd(first);
this.addAtEnd(second);
}