It is easy to add add function to prototype of a value, for example:
Array.prototype.removeAt = function (index) {
if (index >= 0 && index < this.length) {
this.splice(index, 1);
}
return this;
};
declare global {
export interface Array<T> {
removeAt(index: number): Array<T>;
}
}
But it does not work any more when I try to add function to prototype of an interface (which is actually a class, so it has prototype). For example:
import { Router, RouteRecord } from 'vue-router';
Router.prototype.getRouteByName = function (this: Router, name: string): RouteRecord | undefined {
return this.getRoutes().find(m => m.name === name);
};
declare global {
export interface Router {
getRouteByName(name: string): RouteRecord | undefined;
}
}
I get an error when I compile it: 'Router' only refers to a type, but is being used as a value here.
However, the type ‘Router’ is exported as an interface while it is actually a class in the JavaScript code behind, so I think there must be a way to bypass this restriction and mutate its prototype.
Here is how Router
is exported:
export interface Router {
// so many members, please see the detains on
// https://github.com/vuejs/router/blob/main/packages/router/src/router.ts#L189
}
What should I do to achieve it?
2
Answers
Router
is an interface here, not a class function, and more over a router instance is just a plain object so you cannot extend any EXPOSED prototype here, your code doesn’t even run:Just override
createRouter()
any way you like, here I use a class:So import this function and use it instead of the original
createRouter
You extend this not through declare global but
You either need to import this file wherever you wanna use getRouteByName or you have to add it as an ambient type declaration file to you tsconfig. (typeRoots, files,…not sure)
Btw, router is actually a plain JS object so prototyping it might not be so productive just create your own router plugin or router factory function like createRouter that wraps createRouter.