Type 'T | undefined' is not assignable to type 'T'. 'T' could be instantiated with an arbitrary type which could be unrelated to 'T | undefined'

  1. Solution
    1. Approach 1. ! operator
    2. Approach 2. union type

This is a sample TypeScript generic class, which implements a generic Stack class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Stack<T> {
private elements: T[] = [];

constructor(private size: number) {
}
isEmpty(): boolean {
return this.elements.length === 0;
}
isFull(): boolean {
return this.elements.length === this.size;
}
push(element: T): void {
if (this.elements.length === this.size) {
throw new Error('The stack is overflow!');
}
this.elements.push(element);

}
pop(): T {
if (this.elements.length == 0) {
throw new Error('The stack is empty!');
}
return this.elements.pop();
}
}

The code above looks promising, but TypeScript issues an error

1
2
Type 'T | undefined' is not assignable to type 'T'.
'T' could be instantiated with an arbitrary type which could be unrelated to 'T | undefined'.

Solution

Approach 1. ! operator

If you want to return T you should tell TS to exclude undefined from resulting type by using the ! operator.

1
2
3
4
5
6
7
8
9
class Stack<T> {
// .....
pop(): T {
if (this.elements.length == 0) {
throw new Error('The stack is empty!');
}
return this.elements.pop()!; // <==
}
}

Approach 2. union type

1
2
3
4
5
6
7
8
9
class Stack<T> {
// .....
pop(): T | undefined {
if (this.elements.length == 0) {
throw new Error('The stack is empty!');
}
return this.elements.pop();
}
}