如何强类型组合 mixin?

2024-02-03

我正在尝试使用函数组合通过 mixin 向对象添加行为:

const pipe = (...funcs: ((...args: any[]) => any)[]) => (initial: any) => funcs.reduce((object, fn) => fn(object), initial);

  const speakMixin = <T,>(obj: T): T & { speak: () => void } => ({
    ...obj,
    speak: () => console.log("I can speak!")
  });

  const flyMixin = <T,>(obj: T): T & { fly: () => void } => ({
    ...obj,
    fly: () => console.log("i'm flying")
  });

  const chain = pipe(speakMixin, flyMixin);
  const mixed = chain({});

  mixed.fly(); // fly member is typed to any

有没有更好的方法来输入我的pipe函数以便我在应用了 mixin 的对象上获得类型安全?


深入研究这个问题我意识到,我以前的打字compose/pipeline函数在这种情况下没有帮助。

如果你有一组这样的函数,我想你可以这样输入它们:

type Fn = (arg: any) => any

// credits goes to https://stackoverflow.com/a/50375286
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (
  k: infer I
) => void
  ? I
  : never;

const pipe =
  <T extends Fn, Fns extends T[]>(...fns: [...Fns]) =>
    <Data extends Record<string, unknown>>(data: Data) =>
      fns.reduce((acc, fn) => fn(acc), data) as Data & UnionToIntersection<ReturnType<Fns[number]>>;

const speakMixin = <T,>(obj: T) => ({
  ...obj,
  speak: () => console.log("I can speak!")
});

const flyMixin = <T,>(obj: T) => ({
  ...obj,
  fly: () => console.log("i'm flying")
});


// const check: {
//     age: number;
// } & {
//     fly: () => void;
// } & {
//     speak: () => void;
// }
const check = pipe(flyMixin, speakMixin)({ age: 42 })

操场 https://www.typescriptlang.org/play?#code/C4TwDgpgBAYgdlAvFAFAQwE4HMBcU1wgCUSAfPoQFCUD0NUAxhhACYCWwAzlFgPYTdgvKAAtgwMJxx1OwNAwDWvAG4QMAMwA2vAO4A6BrwC2NNDQCsABgDMAdnMAmABwA2SqEhQAqnDa84ACq8AJJwwGqcEAzAfnAAPF7kyCheUBAAHuFwLNwEIFAA-KgKeF4kiOTKvGwsUHhwEKoYJBlZOaiUUFAlUGxw6mpQwZTlldUsnYVDk-WNagDc1IZwslBgbJ6Ik3EBaZkQ2dzwADSwK3tt3AEA2gC6pCh6T+oreNdPevCct6OTXXEAETQcguB3aACUorwMCw4rIMH0sKcAK5wBRwXRwUgPFjAtB4IFyX5dElQF6cPTMFjIhgQFDoBgMU4vUZkuAMhhEU64on4biEtBQABk3l8-iCoXCGEi0VicUhwGRGEC4AgcS+1zgyKMACM1PdSItKMtVpxIGgFABZNjpPpIKA7Y4PXg6gBWeACrJQAG9Jh8Xa7jpMzRALXgUKyTbxNBA9NosCgAETBRgEKAhi0AQkTREoAF8iEaTcAyZoQNbbQhkI7nW6PV7fV1-W6g10tCBw5H-Jxo7H40m2AByIylkCInP5wvUWj0YuMERRHq+uik-BYCD1bV6jCLFd54VQZf0UntztkKBVGq7+j7kVH1cZnoR8+XljXqB543dksMBeKe3rJAKDthWfSnI+oFwEQPprhuUAACwOB+uaUEAA

相关问题列表:[键入管道函数 https://stackoverflow.com/questions/65319258/how-to-type-pipe-function-using-variadic-tuple-types-in-typescript-4, 打字管道功能2 https://stackoverflow.com/questions/65057205/typescript-reduce-an-array-of-function/67760188#67760188, 打字撰写功能 https://stackoverflow.com/questions/68800808/can-you-write-a-compose-method-that-infer-types-correctly-if-the-innermost-fun/68801798#68801798, 我的文章 https://catchts.com/FP-style#compose ]

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何强类型组合 mixin? 的相关文章

随机推荐

  • 如何打印 groupby 对象

    我想打印与 Pandas 分组的结果 我有一个数据框 import pandas as pd df pd DataFrame A one one two three three one B range 6 print df A B 0 on
  • CUDA 不支持边界检查

    我尝试使用 Numba 并访问 GPU 以加速代码 但出现以下错误 in jit raise NotImplementedError bounds checking is not supported for CUDA NotImplemen
  • 测试抛出 IntegrityError 的 SQLAlchemy 代码的正确方法是什么?

    我读过了this https stackoverflow com questions 129507 how do you test that a python function throws an exception问答 并且已经尝试捕获我
  • 在 tfs 中看不到上线选项

    我在离线模式下打开了一个解决方案 但现在我尝试上网并连接到 tfs 但我似乎看不到 文件 gt 源代码管理 下的 上网 按钮 我使用 团队 gt 连接到 Team Foundation Server 选项连接到 TFS 但在 文件 gt 源
  • 将字节数组转换为不使用画布的图像数据

    是否可以在不使用画布的情况下将字节数组转换为图像数据 我目前使用类似的东西 但是我认为可以在没有画布的情况下完成 还是我错了 var canvas document getElementsByTagName canvas 0 var ctx
  • jQuery/Javascript - 淡入 div onclick 淡出另一个不起作用

    我想在点击 div 时弹出一个菜单 我在这个 Fiddle 中一切正常 http jsfiddle net EhtrR 825 http jsfiddle net EhtrR 825 但我无法让它在我的代码上工作 HTML div clas
  • 如何创建一个可以点击其他应用程序的自动点击器应用程序?

    我见过很多提供自动点击功能的应用程序 但他们不提供一些特定的定制 所以我决定创建一个 我看过很多提供自动点击的教程 但它们应该在同一个应用程序中使用 但我想创建一个自动点击应用程序 可以单击其他应用程序的视图 我是一名中级java开发人员
  • Delphi 应用程序如何检测 Windows PC 的网络代理设置?

    我有一个 Delphi 应用程序 它使用以下命令与 Internet 上的 Web 服务器进行通信印地组件 http www indyproject org 该应用程序的大多数用户都具有直接的 Internet 连接 但有些用户位于本地网络
  • Lua 作为嵌入式语言的替代品?

    我正在开发一个在 DSP 上运行 Linux 的嵌入式系统 现在我们想让它的某些部分可以编写脚本 并且我们正在寻找一种很好的嵌入式脚本语言 这些脚本应该与我们现有的 C 代码库很好地集成 并且小而快 我知道 Lua 是解决此类问题的行业选择
  • 将 GCController 与 tvOS 模拟器结合使用

    我没有新的 Apple TV 但正在使用模拟器为其制作游戏原型 不幸的是 我似乎无法让 GCController 将 Siri 遥控器列为可用控制器 正如 tvOS 文档所示 我的控制器列表始终是 0 个元素长 即使我调用startWire
  • OS X 的 Boot2Docker 无法启动

    我是 docker 新手 我正在尝试在我的工作计算机上运行 boot2docker 我使用从办公室网络挂载主目录的用户帐户登录到运行 OS X 版本 10 10 1 Yosemite 的计算机 我安装了 Docker v1 4 1https
  • 禁用内联CSS样式[重复]

    这个问题在这里已经有答案了 当我使用 IE Developer 工具检查 html 时 我发现按钮有一种内联样式 我什么都不想要width此输入元素的属性 如何禁用或用空覆盖它width 如果您想覆盖内联样式 那么您需要在样式表中添加样式
  • Elasticsearch 的 406(不可接受)错误代码是什么意思?

    我正在尝试使用qwest http dreamysource io project qwest将一些数据发送到 Elasticsearch qwest post http elk example com 9200 incidents thi
  • 固定列标题宽度与正文列宽度不匹配

    标题与列宽不对齐 JsFiddle http jsfiddle net DyMSb 1 截屏 http s17 postimg org dybznay9b screen png 我在用着 ajax aspnetcdn com ajax jq
  • 以单下划线或双下划线开头的函数和变量

    我在各种编程语言 PHP 和 Python 中看到过以下划线开头的函数和变量 并且对其背后的含义感到困惑 假设 PHP 中使用正常约定 单下划线表示受保护的成员变量或方法 双下划线表示私有成员变量或方法 这源于当时 PHP 的 OOP 支持
  • 如何让Spring JMS从注释@JmsListener中选择目标队列名称

    任何帮助将不胜感激 我正在尝试使用 spring JMSListener 创建 MDB 的替代品 我希望将目的地名称作为注释传递 但我注意到org springframework jms listener DefaultMessageLis
  • 对象的 JVM 深度内存大小[重复]

    这个问题在这里已经有答案了 据我所知 众所周知的 Instrumentation Java 方法无法正确计算对象的深度大小 是否有可靠的方法在 JVM 上计算对象的正确深度大小 我正在考虑的用例是固定 或上限 内存大小的数据结构 即缓存 注
  • 如何显示多个 YouTube 视频而不重叠音频

    我有一个包含一些 YouTube 视频嵌入代码的页面 当用户在一个视频上单击 gt 播放 时 页面上的所有其他视频都需要暂停 否则它们的音频会与刚刚播放的新视频重叠 实现这一点最有效的方法是什么 好吧 这是我根据其他人的一些代码提出的解决方
  • postgreSQL中的@@Fetch_status

    我正在将数据库从 MS SQL Server 传输到 PostgreSQL 但此触发器有问题 CREATE TRIGGER added clients ON client FOR INSERT AS BEGIN DECLARE cursor
  • 如何强类型组合 mixin?

    我正在尝试使用函数组合通过 mixin 向对象添加行为 const pipe funcs args any gt any gt initial any gt funcs reduce object fn gt fn object initi