在Typescript中,您如何区分Node和Vanilla Javascript Error类型?

时间:2018-07-25 16:16:54

标签: javascript node.js typescript

我具有以下功能:

/**
 * Retrieves a component template from filesystem
 */
const getComponentTemplate = async (
  p: string
): Promise<string> => {
  let template: string
  try {
    template = await fs.readFile(p, {
      encoding: 'utf8'
    })
  } catch (e) {
    if (e instanceof Error && e.code === 'ENOENT') {
      throw new Error(`template for element type ${elementType} not found`)
    }
    throw e
  }

  return template
}

打字稿在这里抱怨:

[ts] Property 'code' does not exist on type 'Error'

这是因为Javascript Error类仅具有属性message and name

但是,Node的Error类确实有一个code property

Typescript在特殊的接口ErrnoException中定义了此名称(请参见源here)。我已将@types/node添加到package.json中,但这并未使Typescript意识到此ErrorErrnoException接口的一部分。

不可能在catch子句中声明类型注释。那么,如何使Typescript编译器能够解决这是一个节点错误?

仅供参考,这是我的tsconfig.json的一部分:

{
  "compilerOptions": {
    "target": "es2017",
    "module": "commonjs",
    "lib": ["es2017"]
    ...
  }
}

3 个答案:

答案 0 :(得分:1)

您可以考虑使用方括号读取code属性,然后检查其值是否等于ENOENT

try {
    ...
} catch (e) {
    const code: string = e['code'];
    if (code === 'ENOENT') {
        ...
    }
    throw e
}

这不是一个完美的解决方案,但考虑到您不能在catch子句中声明类型并且e instanceof ErrnoException检查不能正常工作(如问题注释中所述),这可能就足够了。 / p>

答案 1 :(得分:1)

如果要使用try / catch,则会得到一个不知道其类型的对象。

您已经测试过的代码可以查看该对象是否为Error,如果是,则将其强制转换为“普通” JS Error对象。

您可以使用typeguard来告诉类型系统对象实际上是什么类型。

类似的东西:

function isError(error: any): error is ErrnoException { return error instanceof Error; }

我看过fs.readFile,这似乎是使用该函数的一种常见方式,实际上整个节点api都是通过向其传递一个回调,该回调在工作完成或存在时被调用是一个错误。

看着type definition,它表明传递给回调的错误对象确实是所需的ErrnoException

export function readFile(path: PathLike | number, callback: (err: NodeJS.ErrnoException, data: Buffer) => void): void;

因此,使用回调将消除对类型防护的需要,并且似乎是实现此目标的节点方法。

This article显然详述了“回调万物”方法背后的一些想法。

  

Node对回调的大量使用可以追溯到一种编程风格   比JavaScript本身更旧。持续通过风格(CPS)是   Node.js今天如何使用回调的老式名称。在CPS中,   “ continuation function”(读取:“ callback”)作为参数传递给   该代码的其余部分运行后将被调用。这允许   不同的功能来回手动异步控制   整个应用程序。

     

Node.js依靠异步代码保持快速运行,因此   可靠的回调模式至关重要。没有一个,开发人员就会   被困在彼此之间保持不同的签名和样式   每个模块。错误优先模式已引入Node核心,以   解决了这个问题,并自此传播到今天   标准。虽然每个用例都有不同的要求,   响应,错误优先模式可以容纳所有响应。

答案 2 :(得分:0)

我最终使用@AndyJ的评论:

/**
 * Retrieves a component template from filesystem
 */
const getComponentTemplate = async (
  p: string
): Promise<string> => {
  let template: string
  try {
    template = await fs.readFile(p, {
      encoding: 'utf8'
    })
  } catch (e) {
    // tslint:disable-next-line:no-unsafe-any
    if (isNodeError(e) && e.code === 'ENOENT') {
      throw new Error(`template for element type ${elementType} not found`)
    }
    throw e
  }

  return template
}

/**
 * @param error the error object.
 * @returns if given error object is a NodeJS error.
 */
const isNodeError = (error: Error): error is NodeJS.ErrnoException =>
  error instanceof Error

但是我很惊讶地看到这是必要的。另外,如果您使用不安全的规则,它还要求您disable tslint's