gpt4 book ai didi

node.js - Typescript - 为 'promisifed' 方法添加类型

转载 作者:搜寻专家 更新时间:2023-10-30 21:09:59 27 4
gpt4 key购买 nike

我有一个非常简单的模块,它包装了“fs”模块。该模块简单地“promisifies”所有“fs”方法并导出新对象:

fsWrapper.ts

import Promise from "bluebird";
import * as fs from "fs";

const fsWrapper = Promise.promisifyAll(fs);

export = fsWrapper;

现在我可以使用这个包装器而不是在每个调用者模块中“promisifiying”“fs”模块,就像这样:

main.ts

import fsWrapper from "./fsWrapper";

function test(): void {
fsWrapper.readFileAsync("tst.txt", "utf8")
.then((data: Buffer) => {
console.log("data:", data.toString());
})

这当然不适用于 typescript ,因为“fs”不包含 readFileAsync 方法并且我收到编译器错误。

在搜索正确键入此包装器的方法时,我找到了 following typescript issue .

使用它的方法,我可以创建自己的 fsWrapper.d.ts,我需要在其中手动添加 *Async 方法,类似于以下内容:

fsWrapper.d.ts

import Promise from "bluebird";

declare module "fs" {
export function readFileAsync(path: string, options: { encoding?: string | null; flag?: string; } | string | undefined | null) : Promise<Buffer>;
...
}

这里的问题是:

  1. 手动添加所有需要的方法既乏味又容易出错。
  2. 如果这些方法在未来的版本中会发生变化,我将不知道,因为我的代码会继续编译并且我会遇到运行时异常。

我知道 util.promisify 的类型正确,因此想到用这些新方法以某种方式扩展“fs”,类似于以下内容:

fsWrapperTest.ts

import * as fs from "fs";
import { promisify } from "util";

let fsWrapper = fs;
fsWrapper.readFileAsync = promisify(fs.readFile);

export = fsWrapper;

但这会输出一个错误,表明我无法扩展现有模块:错误 TS2551:属性“readFileAsync”在类型“typeof“fs””上不存在。您是说“readFileSync”吗?

有什么方法可以让我在保持“最新”打字并使用 Intellisense 的同时正确地键入此包装器?

编辑:澄清一下,我了解如何创建一个对象,该对象将所有“fs”方法都 promisified(上面的原始 fsWrapper.ts 就是这种情况)。

我正在努力的是正确输入它以供 Intellisense 使用。例如,运行以下命令:

import * as fs from "fs";
import { promisify } from "util";

let fsWrapper = Object.keys(fs).reduce((p: typeof fs, v: string) => { p[v] = promisify(fs[v]); return p }, {})

会给我一个 fsWrapper:{} 对象输入。

我希望将所有“fs”方法 + 新的“promisifed”方法作为其类型。

编辑 - 选定的解决方案

我最终使用了 declare module 'fs' 方法,方法是使用我在代码中使用的所有 *Async 方法扩展“fs”模块。不理想,但似乎没有更好的选择..

最佳答案

如果您使用的是 TypeScript 3.0 或更新版本,映射类型和参数元组的改进应该可以实现这一点。例如:

type UnpackedPromise<T> = T extends Promise<infer U> ? U : T
type GenericFunction<TS extends any[], R> = (...args: TS) => R
type Promisify<T> = {
[K in keyof T]: T[K] extends GenericFunction<infer TS, infer R>
? (...args: TS) => Promise<UnpackedPromise<R>>
: never
}

这会创建一个用于展开 promise 的类型,一个用于泛型函数的类型,然后是一个用于 promise 版本的推断映射类型,它将每个键映射到一个新值,该新值是前一个函数的 promise 版本。要使用该类型 ( playground link ):

const original = {
one: () => 1,
two: () => 2,
add: (a: number, b: number) => a + b
}

const promisified = original as unknown as Promisify<typeof original>

promisified.one()
promisified.add(1, 2)

对于您的示例,这是如何使用它的:

import * as fs from "fs";
import { promisify } from "util";

let fsWrapper = Object
.keys(fs)
.reduce((p: typeof fs, v: string) => { p[v] = promisify(fs[v]); return p }, {}) as unknown as Promisify<typeof fs>

请注意,您正在转换为 unknown,然后转换为 Promisify<*> - 这是因为默认情况下它会认为映射类型可能是错误的。

关于node.js - Typescript - 为 'promisifed' 方法添加类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52691279/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com