创建映射类型以承诺返回值

2023-12-31

假设我正在处理与以下接口相对应的对象:

interface Foo {
    getCount(): number;
    doSomething(): boolean;
}

它只有函数,并且没有一个函数是异步的。但是,我并不总是能够同步访问该对象,并且在某些情况下将处理异步版本,其中所有函数返回值都包装在 Promises 中。就像这样:

interface AsyncFoo {
    getCount(): Promise<number>;
    doSomething(): Promise<boolean>;
}

我正在尝试创建一个 Typescript 映射类型来表示这种转换,因为我有大量的对象接口,并且不想简单地复制每个接口并最终得到两个接口interface [name] and interface Async[name]并且所有方法原型都是重复的。

我的第一个想法是也许我可以像这样修改接口:

type Self<T> = T;
interface Foo<S = Self> {
    getCount(): S<number>;
    doSomething(): S<boolean;
}
type AsyncFoo = Foo<Promise>;

但两者Self and Promise要求在使用泛型时静态给出它们,而不是能够以这种向后的方式使用它们。

接下来我尝试创建某种映射类型,例如:

type Promisify<T> = {[K in keyof T]: Promise<T[K]>}

当然,这将接口的每个完整方法包装在 Promise 中,而不仅仅是返回值,给我:

type PromisifiedFoo = {
    getCount: Promise<() => number>;
    doSomething: Promise<() => boolean>;
}

我尝试通过使用通用范围来扩展这一点T of Promisify like:

type Promisify<T extends {[key: string]: <S>() => S}> = ...

但我似乎无法将它们整合在一起。

所以现在我在这里。有什么方法可以让我构建一个类型(映射或其他方式)来表示这种“Promisify”转换到类型的返回值上?


随着新条件类型 https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html在 Typescript 2.8 中,您可以执行以下操作:

// Generic Function definition
type AnyFunction = (...args: any[]) => any;
// Extracts the type if wrapped by a Promise
type Unpacked<T> = T extends Promise<infer U> ? U : T;

type PromisifiedFunction<T extends AnyFunction> =
    T extends () => infer U ? () => Promise<Unpacked<U>> :
    T extends (a1: infer A1) => infer U ? (a1: A1) => Promise<Unpacked<U>> :
    T extends (a1: infer A1, a2: infer A2) => infer U ? (a1: A1, a2: A2) => Promise<Unpacked<U>> :
    T extends (a1: infer A1, a2: infer A2, a3: infer A3) => infer U ? (a1: A1, a2: A2, a3: A3) => Promise<Unpacked<U>> :
    // ...
    T extends (...args: any[]) => infer U ? (...args: any[]) => Promise<Unpacked<U>> : T;

type Promisified<T> = {
    [K in keyof T]: T[K] extends AnyFunction ? PromisifiedFunction<T[K]> : never
}

Example:

interface HelloService {
    /**
    * Greets the given name
    * @param name 
    */
    greet(name: string): string;
}

function createRemoteService<T>(): Promisified<T> { /*...*/ }

const hello = createRemoteService<HelloService>();
// typeof hello = Promisified<HelloService>
hello.greet("world").then(str => { /*...*/ })
// typeof hello.greet = (a1: string) => Promise<string>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

创建映射类型以承诺返回值 的相关文章

随机推荐

  • 如何在 Python 中将 Excel 工作表另存为 HTML?

    我正在与这个图书馆合作XlsxWriter https pypi python org pypi XlsxWriter 我打开了一本工作簿并在其中写了一些内容 考虑官方的例子 http xlsxwriter readthedocs org
  • ERR_BAD_SSL_CLIENT_AUTH_CERT

    我们在浏览大多数 https 网站时开始遇到问题 示例包括 https technet microsoft com https technet microsoft com https mail google com https mail g
  • 是否可以使用 addEventListener 调用类方法?

    只是我一直想知道的事情 在第二个参数中 addEventListener方法 您可以调用 自定义 类方法 而不是函数吗 即像下面这样的东西会起作用吗 var object new ClassName document getElementB
  • UIScrollView 滚动时重绘内容?

    我知道有一个属性或方法可以使scrollview uiview 在滚动时调用drawRect 方法 由于性能原因 默认情况下处于禁用状态 但我需要启用它 我不记得该方法的名称 因此我无法寻找它 有人知道我在寻找什么吗 提前致谢 我建议使用s
  • QTreeWidget 内的 QT 可点击小部件(可能是按钮)?

    我有一个基本上是 QTreeWidget 的表 我想在其中放置一个可点击的小部件 可能是一个按钮 每行都是一个 QTreeWidgetItem 但我不知道如何使用 QTreeWidgetItem setData 添加按钮 这是对 Qt 文档
  • 无法从 C# 中的 .Net 套接字正确读取数据

    我有一个使用套接字通信的 C 客户端和服务器类 服务器看起来像这样 public class AsyncTcpServer private Socket server socket private Socket client socket
  • iPhone OpenGL ES 不正确的 alpha 混合

    我在 iPhone 上使用 openGL ES 时遇到了不正确的 alpha 混合结果的问题 这是我创建纹理对象的代码 glGenTextures 1 tex name glBindTexture GL TEXTURE 2D tex nam
  • Windows CDROM 弹出

    有谁知道在 Windows 2000 或更高版本上以编程方式关闭 CD 托盘的方法吗 打开 CD 托盘存在 但我似乎无法关闭它 尤其是在 W2k 下 如果可能的话 我特别寻找一种从批处理文件中执行此操作的方法 但 API 调用也可以 我有点
  • CSS 向右浮动无法正常工作

    我的右侧浮子没有按我预期的方式工作 我希望我的按钮能够很好地对齐到一行上方文本的右侧 div style padding 5px border bottom width 1px border bottom color gray border
  • 在帖子上发帖时遇到“(#100) 查找请求的故事时出错”

    我正在使用 Graph API 来获取用户被标记的帖子 然后通过以下方式对帖子进行点赞POSTing to post id likes 然而 即使该帖子显然存在 因为我能够检索到post id 发出like时 遇到如下错误 100 Erro
  • C# 跟踪截断长消息

    在 C 中 我启用了跟踪和网络跟踪源
  • 是否有一种算法可以将威胁范围与二维网格上的任意移动范围相结合?

    我正在构建一个简单的基于 2D 网格的游戏 并正在寻找一种方法来计算每个角色可以在游戏板上施加的 威胁 区域 当前地点的威胁很容易计算 这是下面的红色菱形 但我希望将这些信息与任意 可以步行到这里 区域 橙色 结合起来 该算法一起会给我我的
  • 如何链接docker容器?

    我尝试链接我的 docker 容器 但似乎在访问时出错 我的结构如下 数据库docker Mysql 容器名称是um mysql 后端 docker Tomcat 镜像名称为cz um app 前端 docker Nginx 镜像名称为cz
  • 如何从 OAuth2 授权服务器/用户端点获取自定义用户信息

    我有一个资源服务器配置为 EnableResourceServer注释 它通过以下方式引用授权服务器user info uri参数如下 security oauth2 resource user info uri http localhos
  • Visual Studio 中的包目录是什么?我应该将它包含在 SVN 中吗?

    我第一次在 Visual Studio 2010 中使用 ASP NET MVC 4 并使用 SVN 控制源代码 我曾经在 Visual Studio 2008 中使用 MVC 1 其中我有自己的 svn ignore 过滤器 pdb ex
  • 如何在 C# 中从网络摄像头获取持续的位图图像流

    我们有一个对视频流执行处理的 C 应用程序 这是一个低级应用程序 以位图格式接收每一帧 因此基本上我们每秒需要 25 个图像 该应用程序已经适用于我们的一些媒体源 但我们现在需要添加网络摄像头作为输入设备 因此 我们基本上需要从网络摄像头连
  • 使用 Angular 访问数据库

    是否可以在 Angular 框架中访问 MySQL 数据库 或者像其他 Javascript 一样不安全 我需要发布到 PHP 页面来检索data json来自数据库 1 是否可以在角度框架中访问MySQL数据库 这个问题不是特定于角度的
  • JavaScript 模块模式中的方括号表示法和范围

    我一直在使用 JavaScript 中的模块模式 并且对范围和方括号表示法 SBN 有疑问 请考虑以下简单示例 function module function myMethod text console log text module i
  • 如何使用 mysqli::bind_param 并将数组作为第二个参数

    该查询应该将新用户插入 users 表中 user DB getInstance gt insert users array username gt jim password gt pass salt gt salt 对应insert pu
  • 创建映射类型以承诺返回值

    假设我正在处理与以下接口相对应的对象 interface Foo getCount number doSomething boolean 它只有函数 并且没有一个函数是异步的 但是 我并不总是能够同步访问该对象 并且在某些情况下将处理异步版