I am writing 2 classes, Project and User, each of which has a find method that needs to call an api rest call
attempt #1
class Project {
find(params) {
return request({url: "/api/Project", qs: params});
}
}
class User {
find(params) {
return request({url: "/api/User", qs: params});
}
}
now, this is obviously not very good ;) There are no checks on the parameters, no types defined, duplicate code etc etc
attempt #2
class Base {
constructor(private name:string) {
}
find(options) {
return request({url: `/api/${this.name}`, qs: params});
}
}
class Project extends Base{
constructor() { super("Project"); }
}
class User {
constructor() { super("User"); }
}
so, slightly better. less code duplication. Still no type checking. Interfaces to the rescue ;)
attempt#3
interface IParams { token: string }
class Base {
constructor(private name:string) {
}
find(params:IParams) {
return request({url: `/api/${this.name}`, qs: params});
}
}
class Project extends Base{
constructor() { super("Project"); }
}
class User extends Base {
constructor() { super("User"); }
}
this is where I started to hit some problems. The Project and User api params object both require the token property. However, they also require userDd and projectId to be set
At the moment, I need to add both of those to the IParams interface, which seems wrong.
attempt#4
interface IUserParams { userid:number, token: string }
interface IProjectParams { projectid:number, token: string }
interface IProject {
find(params:IProjectParams)
}
interface IUser {
find(params:IUserParams)
}
class Base {
constructor(private name:string) {
}
find(params) { // I have no idea on how to "type" params
return request({url: `/api/${this.name}`, qs: params}); // likewise no idea on how to type the return value
}
}
class Project extends Base implements IProject {
constructor() { super("Project"); }
}
class User extends Base implements IUser {
constructor() { super("User"); }
}
However, this does not help : as the Base class defines the find method, how can the compiler verify that for user, userid and token are passed - also, that no other parameter is passed, and likewise for project
This also led me onto thinking about the return value of the find method : for projects I want an array of IPromiseModel, and for user, IUserModel
I have tried chaning the IProject interface to read
interface IProject {
find(params:IProjectParams):Promise<IProjectModel[]>
}
but I still can pass any property into the params - ie I can do
Project.find({token: "1234",foobar:true})
I suspect this is because I haven't defined a type for the parameter in the Base find
I know that generics must play a part in this, but for the life of me I cannot get a definition working that matches these requirements
I am using typescript 2.2.2
anyinto derived class methods because they hide the base method. This means that the declared type is actually that of the find methods in the derived classes.Projecthas the type of the class, the same reasoning applies.