I've implemented an abstract, generic RESTClient. Sometimes not all REST actions are implemented, so I want to throw an error in that case.
If I override the method TypeScript expects me to return the specified type, even though I throw the error. If I add return null
it compiles, but the return is unreachable.
export class RESTClient<E extends { id: number }, D = Omit<E, 'id'>> extends Client {
protected path: string;
public constructor(path: string, token?: string) {
super(token);
this.path = path;
}
public update(entity: E) {
return this.clientInstance.put<E>(`${this.path}/${entity.id}`, entity);
}
}
export class ItemClient extends RESTClient<Item> {
public constructor(token?: string) {
super('items', token);
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
public delete(_entity: Item) {
throw new Error('Not supported by API');
}
}
How can I correctly implement this in TypeScript (version 3.7.2
)?
You can use never
as the return type for the implementing method. It's assignable to every other type:
interface Item {
id: number;
}
export class RESTClient<E extends { id: number }> {
public update(entity: E) {
return entity;
}
}
export class ItemClient extends RESTClient<Item> {
public update(entity: Item): never {
throw new Error('Not supported by API');
}
}
The suitable excerpt from the documentation:
The
never
type is a subtype of, and assignable to, every type; however, no type is a subtype of, or assignable to,never
(exceptnever
itself). Evenany
isn’t assignable tonever
.