简体   繁体   English

打字稿类,接口和泛型

[英]typescript classes, interfaces and generics

I am writing 2 classes, Project and User , each of which has a find method that needs to call an api rest call 我正在编写ProjectUser这两个类,每个类都有一个find方法,需要调用api rest调用

attempt #1 尝试#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 尝试#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 尝试#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. Project和User api params对象都需要token属性。 However, they also require userDd and projectId to be set 但是,它们还需要设置userDdprojectId

At the moment, I need to add both of those to the IParams interface, which seems wrong. 目前,我需要将两者都添加到IParams接口中,这似乎是错误的。

attempt#4 尝试#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 但是,这无济于事:因为基类定义了find方法,编译器如何才能验证是否为用户, useridtoken传递了-此外,也没有其他参数传递给项目,同样对于项目也是如此

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 这也使我开始思考find方法的返回值:对于项目,我需要IPromiseModel数组,对于用户,则是IUserModel

I have tried chaning the IProject interface to read 我尝试更改IProject接口以读取

interface IProject {
    find(params:IProjectParams):Promise<IProjectModel[]>
}

but I still can pass any property into the params - ie I can do 但我仍然可以将任何属性传递给params -即我可以

Project.find({token: "1234",foobar:true})

I suspect this is because I haven't defined a type for the parameter in the Base find 我怀疑这是因为我没有在Base查找中为参数定义类型

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 我正在使用打字稿2.2.2

With generics you can do this: 使用泛型,您可以执行以下操作:

interface IParams { token: string }
interface IUserParams { userid:number, token: string }
interface IProjectParams { projectid:number, token: string }

class Base<TEntity, TParams extends IParams> {
    constructor(private name:string) {
    }

    find(params: TParams): Promise<TEntity[]> {
        return request({url: `/api/${this.name}`, qs: params});
    }
}

class Project extends Base<Project, IProjectParams> {
    constructor() { super("Project"); }
}

class User extends Base<User, IUserParams> {
    constructor() { super("User"); }
}

new User().find({
    userid: 123,
    token: 'test'
});

The constraint in the Base class TParams extends IParams here is optional, since you are not explicitly accessing the token property. 基类TParams extends IParams的约束在这里TParams extends IParams是可选的,因为您没有显式访问令牌属性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM