Reputation: 1191
Like other JS devs, I somewhat new to thinking about writing things in a static way that the TypeScript compiler can understand. My basic use-case is customizing the actions available on a generic class for accessing a REST endpoint. I can dynamically add methods/props to the base class based on constructor arguments, but doing things that dynamically (understandably) makes the intellisense incorrect. I know I am just thinking about this wrong, and there is a different paradigm for achieving what I want. How can I customize a base class from its children in a way the compiler understands?
Here is what I'm trying:
class Endpoint<T> {
constructor(
methods: Array<'GET' | 'CREATE'>
) {
// Conditionally add methods to the endpoint based on what was passed in
if (methods.includes('GET')) {
this.get = function get(id: string): Promise<T> {
return new Promise<T>(resolve => resolve());
};
}
if (methods.includes('CREATE')) {
this.create = function create(body: T): Promise<T> {
return new Promise<T>(resolve => resolve());
};
}
}
public get?: (id: string) => Promise<T>;
public create?: (body: T) => Promise<T>;
}
class User extends Endpoint<IUser> {
constructor() {
super(['GET']);
}
}
let u = new User();
// u.create will get transpiled away, but still shows up in intellisense
Upvotes: 1
Views: 85
Reputation: 106690
You might be able to shorten this code and it's not pretty, but the basic idea is to use mixins which were introduced in Typescript 2.2:
class Endpoint<T> {
}
type Constructor<T> = new(...args: any[]) => T;
function Gettable<T, U extends Constructor<Endpoint<T>> = typeof Endpoint>(Base: U) {
return class extends Base {
get(id: string): Promise<T> {
return new Promise<T>(resolve => resolve());
}
}
}
function Createable<T, U extends Constructor<Endpoint<T>> = typeof Endpoint>(Base: U) {
return class extends Base {
create(body: T): Promise<T> {
return new Promise<T>(resolve => resolve());
}
}
}
class User extends Gettable<IUser>(Endpoint)<IUser> {
}
const u = new User();
u.get("id"); // ok
u.create(); // error, method doesn't exist
Upvotes: 1