我具有以下功能:
/**
* 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意识到此Error
是ErrnoException
接口的一部分。
不可能在catch子句中声明类型注释。那么,如何使Typescript编译器能够解决这是一个节点错误?
仅供参考,这是我的tsconfig.json
的一部分:
{
"compilerOptions": {
"target": "es2017",
"module": "commonjs",
"lib": ["es2017"]
...
}
}
答案 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。