我如何才能强烈地键入合成的混合成分? [英] How can I strongly type a composed mixin?

查看:0
本文介绍了我如何才能强烈地键入合成的混合成分?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用函数组合将行为添加到具有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函数,以便我在已应用混合的对象上获得类型安全?

推荐答案

深入研究这个问题我已经意识到,我以前键入的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 })

Playground

相关问题列表:[typing pipe functiontyping pipe function 2typing compose functionmy article]

这篇关于我如何才能强烈地键入合成的混合成分?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆