【问题标题】:typescript classes, interfaces and generics打字稿类、接口和泛型
【发布时间】:2017-09-26 08:57:11
【问题描述】:

我正在写2个类,ProjectUser,每个类都有一个find方法,需要调用一个api rest call

尝试 #1

class Project {
  find(params) { 
    return request({url: "/api/Project", qs: params});
  }
}

class User {
  find(params) { 
    return request({url: "/api/User", qs: params});
  }
}

现在,这显然不是很好;)没有检查参数,没有定义类型,重复代码等

尝试 #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"); }    
}

所以,稍微好一点。更少的代码重复。仍然没有类型检查。救援接口;)

尝试#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"); }    
}

这是我开始遇到一些问题的地方。 Project 和 User api 参数对象都需要 token 属性。但是,它们还需要设置 userDdprojectId

目前,我需要将这两个都添加到 IParams 接口中,这似乎是错误的。

尝试#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"); }    
}

然而,这无济于事:由于基类定义了find 方法,编译器如何验证用户,useridtoken 是否被传递 - 而且,没有其他参数 已通过,项目也是如此

这也让我想到了 find 方法的返回值:对于项目我想要一个 IPromiseModel 的数组,对于用户,IUserModel

我已尝试将IProject 界面改为阅读

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

但我仍然可以将 any 属性传递给params - 即我可以做到

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

我怀疑这是因为我没有在 Base find 中为参数定义类型

知道泛型必须在其中发挥作用,但在我的一生中,我无法找到符合这些要求的定义

我正在使用打字稿 2.2.2

【问题讨论】:

  • 您可以将any 传递给派生类方法,因为它们隐藏了基方法。这意味着声明的类型实际上是派生类中查找方法的类型。
  • 这就是我的想法/希望 - 但是为什么编译器允许我将“foobar”作为 IProjectParams 的属性之一传递?
  • 如果Project 具有类的类型,同样的推理也适用。
  • FWIW 我只会使用一个函数和一些接口。

标签: typescript


【解决方案1】:

使用泛型你可以这样做:

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'
});

此处基类TParams extends IParams 中的约束是可选的,因为您没有显式访问令牌属性。

【讨论】:

  • 哇。谢谢-我一直在尝试使用这种结构。但是,我遇到了几个问题:1)'find' 方法正在返回一个承诺,所以签名不应该是“Promise>”,以及带有单元测试和 mocha 的#2,我现在得到一个错误编译单元测试“错误TS2339:属性'rejectedWith'在'Assertion'类型上不存在。”我的测试是“Project.find({token:"invalidToken"}).should.be.rejectedWith({statusCode: 401});” - 但是 "Project.find({token:"validToken"}).then((data) => {" 工作得很好
  • 是的,返回类型应该如你所说。关于测试中的错误,我想可能与这个库的类型定义有关。
  • 安装“@types/chai-as-promised”提供了打字稿所需的类型定义。
猜你喜欢
  • 2018-12-27
  • 2021-11-26
  • 2017-09-15
  • 2020-01-23
  • 2019-03-12
  • 2020-04-13
  • 2019-01-16
  • 2021-04-20
  • 1970-01-01
相关资源
最近更新 更多