简体   繁体   English

如何重用链式函数 Javascript + Typescript

[英]How to reuse chained functions Javascript + Typescript

I'm using Typescript and creating a form validation library with chained methods, but I'm stuck trying to reuse functions because of the this return, I will exemplify in a simpler way:我正在使用 Typescript 并创建一个带有链式方法的表单验证库,但由于this返回,我一直试图重用函数,我将以更简单的方式举例说明:

const schema = {
  computer() {
    return {
      turnOn() {
        console.log('turn on')
        return this
      },
      openVscode() {
        console.log('open vscode')

        return this
      },
      work() {
        console.log('work')
        return this
      },
      turnOff() {
        console.log('turn off')
        return this
      }
    }
  },
  phone() {
    return {
      turnOn() {
        console.log('turn on')
        return this
      },
      takeSelfies() {
        console.log('take selfies')

        return this
      },
      callToMom() {
        console.log('call to mom')
        return this
      },
      turnOff() {
        console.log('turn off')
        return this
      }
    }
  }
}

everything works fine.一切正常。

const devices = {
  iMac: schema.computer().turnOn().openVscode().work().turnOff(),
  iPhone: schema.phone().turnOn().takeSelfies().callToMom().turnOff()
}

but when I try to separate the repeated functions in another file, for example但是当我尝试在另一个文件中分离重复的功能时,例如

const mixed = {
  turnOn() {
    console.log('turn on')
    return this
  },
  turnOff() {
    console.log('turn off')
    return this
  }
}

to reuse重用

const newSchema = {
  computer() {
    return {
      ...mixed,
      openVscode() {
        console.log('open vscode')

        return this
      },
      work() {
        console.log('work')
        return this
      }
    }
  },
  phone() {
    return {
      ...mixed,
      takeSelfies() {
        console.log('take selfies')

        return this
      },
      callToMom() {
        console.log('call to mom')
        return this
      }
    }
  }
}

I'm stuck我被困住了

在此处输入图像描述

I know this is because the this of the mixed object returns only the content itself, but I don't know how to solve this problem.我知道这是因为mixed object 的this只返回内容本身,但我不知道如何解决这个问题。

I thank you all!我谢谢大家!

This is an example of the pattern known as Mixins and is developed in typescript as Decorators这是称为Mixins的模式的一个示例,在 typescript 中作为装饰器开发

The basic idea is to join two classes together to provide functionality similar to classical inheritance.基本思想是将两个类连接在一起以提供类似于经典 inheritance 的功能。 It starts off with simple copying of object properties - but could be developed into functions that use closures to provide mixins at various levels.它从简单复制 object 属性开始 - 但可以开发成使用闭包提供不同级别的混合的函数。

Here is a proof of concept:这是一个概念证明:

 utility = {foo: function() {return this}} main = {bar: function() {return this}} main = Object.assign(main, utility); console.log(main.foo());

The points made by captain-yossarian and Charlie about mixins are good and worth investigating if you want use them. Captain-yossarian 和 Charlie 关于 mixin 的观点很好,如果你想使用它们,值得研究。 However, here's a solution that doesn't require much refactoring of the original code:但是,这是一个不需要对原始代码进行太多重构的解决方案:

const mixed = { /* same as before */ }

type AnyFn = (...args: never[]) => unknown

type SetReturnTypes<T extends Record<string, AnyFn>> = {
  [K in keyof T]: (...args: Parameters<T[K]>) => SetReturnTypes<T>
}

const makeMixed = <T>(obj: T & ThisType<T & typeof mixed>): SetReturnTypes<T & typeof mixed> => ({
  ...mixed,
  ...obj
}) as unknown as SetReturnTypes<T & typeof mixed>

const newSchema = {
  computer() {
    return makeMixed({
      openVscode() {
        console.log('open vscode')
        return this
      },
      work() {
        console.log('work')
        return this
      }
    })
  },
  phone() {
    return makeMixed({
      takeSelfies() {
        console.log('take selfies')
        return this
      },
      callToMom() {
        console.log('call to mom')
        return this
      }
    })
  }
}

newSchema.computer().turnOn().openVscode()
  • SetReturnTypes makes all methods of T return the correct this type, assuming all these methods return this . SetReturnTypes使T的所有方法都返回正确的this类型,假设所有这些方法都返回this
  • makeMixed is a helper to create an object with mixed with the correct types. makeMixed是一个帮助创建一个mixed了正确类型的 object。 It uses ThisType so that the methods in obj have the correct this type:它使用ThisType以便obj中的方法具有正确的this类型:
makeMixed({
  doSomething() {
    this.turnOn() // would be a compile error without the ThisType
    return this
  }
})

An issue with this is that methods not returning this are incorrectly typed.一个问题是不返回this的方法输入错误。 If you want to ensure that all the methods return this , let me know and I may be able to come up with a solution for that.如果您想确保所有方法都返回this ,请告诉我,我可能会为此提出解决方案。

Playground link 游乐场链接

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM