【问题标题】:How can I strongly type a composed mixin?如何强输入组合的 mixin?
【发布时间】:2021-12-05 13:23:48
【问题描述】:

我正在尝试使用功能组合通过 mixins 向对象添加行为:

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 函数,以便我在应用了 mixins 的对象上获得类型安全?

【问题讨论】:

标签: typescript type-inference typescript-generics


【解决方案1】:

深入研究这个问题,我意识到,我之前输入的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 function,typing pipe function 2,typing compose function,my article]

【讨论】:

    猜你喜欢
    • 2016-08-08
    • 2021-07-15
    • 2017-06-19
    • 1970-01-01
    • 1970-01-01
    • 2021-12-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多