首页 > 解决方案 > 在导入的模块(jsonrpc-lite)中声明类型时如何使用类型保护?

问题描述

我正在尝试设置类型保护,以便后续代码知道对象属于某种类型并可以推断其属性。但是,我不知道如何引用我要检查的类型。该类型位于 npm 模块 (jsonrpc-lite) 中。

如何在我的类型保护中引用类型?

我正在使用打字稿版本 3.2。请注意:我是打字稿的新手!

第一次尝试(没有类型保护):

// somefile.ts
import * as jsonrpc from "jsonrpc-lite"

export const foo = (
  req: express.Request,
  res: express.Response,
  next: express.NextFunction
) => {

  const payload = jsonrpc.parseObject(req.body).payload // fine!
  console.log(payload.id) // Fails!
  // Gives me: Property 'id' does not exist on type 'SuccessObject | NotificationObject | RequestObject | ErrorObject | JsonRpcError'

// ...
}

第二次尝试:

我知道id如果类型为 ,则该属性在有效负载上可用RequestObject,所以我想我可以使用类型保护来扩充代码。

我假设RequestObject类型必须首先对类型系统可见,因为它说Property 'id' does not exist on type 'SuccessObject | NotificationObject | RequestObject | ErrorObject | JsonRpcError'

但是,我不知道如何RequestObject在我的类型保护中引用 jsonrpc-lite - 请参阅下面的问号。


  // My type guard
  // The problem is that I don't know what to write in place of ??????. 
  // I want to reference jsonrpc-lite's RequestObject type:
  const isRequestObj = (payload: any): payload is ?????? => {
    return true
  }

这是 jsonrpc-lite 的 d.ts 文件:https ://github.com/teambition/jsonrpc-lite/blob/master/jsonrpc.d.ts

标签: typescript

解决方案


首先,最好的解决方案是说服包的开发人员导出所有重要的类型。因为对包的任何更新都可能导致其他解决方案停止工作。

下一个最佳解决方案是进行结构类型匹配并仅区分您真正使用的那些属性:

const hasId = (payload: any): payload is { id: string } =>
  typeof payload === 'object' && typeof payload.id === 'string';

但由于问题实际上是关于检索类型,所以这里是如何做到这一点,甚至认为它可能会停止使用更新:

type payload = ReturnType<typeof jsonrpc.parseObject>["payload"];

type matchRequest<T> = T extends {
    id: string | number;
    method: string;
    params?: object;
} ? T : never;

type RequestObject = matchRequest<payload>;

推荐阅读