减少使用特殊方法的课堂打字

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了减少使用特殊方法的课堂打字相关的知识,希望对你有一定的参考价值。

我正在寻找一种减少打字稿输入中冗余的方法。我正在创建一种特定类型的类,其中:

  • 类中的每个方法都有一个参数
  • 对于每个参数键,都有相应的方法
  • 该方法中还允许使用来自该对应方法的参数(仅第一和唯一)。

这是一个可行的课程示例:

interface Wood {}
interface Chair {}
interface DiningRoom {}
interface LivingRoom {}
interface Nail {}

class House {

    constructor () {

    }

    wood (i: {tree: string}): Wood {
        return {}
    }

    nails (i: {nails: number}): Nail[] {
        return [{}]
    }

    chair (i: {wood: Wood, nails: Nail[]} 
        & Parameters<House['wood']>[0]
        & Parameters<House['nails']>[0]    
    ): Chair {
        return {}
    }

    diningRoom (i: {chair: Chair } & Parameters<House['chair']>[0]): DiningRoom {
        return {}
    }

    livingRoom (i: {chair: Chair } & Parameters<House['chair']>[0]): LivingRoom {
        return {}
    }

}

我正在寻找抽象类通用类型,这将减少编写& Parameters<House['wood']>[0]的麻烦。理想情况下,一个抽象类将能够将i: {chair: Chair}作为参数并知道要添加& Parameters<House['chair']>[0]

答案

我不确定我是否了解您在做什么,而且我不知道是否有可能通过继承执行任何操作,从而使子类方法参数自动与事物相交。据我所知,与您的参数相对应的通用类型如下所示:

type AllKeys<T> = T extends any ? keyof T : never;
type MakeParam<H extends Record<K, (x: any) => any>, K extends keyof any> =
  { [Q in K]: Parameters<H[Q]>[0] }[K] extends infer L ?
  { [Q in AllKeys<L>]: Extract<L, Record<Q, any>>[Q] } extends infer M ?
  { [P in K | keyof M]:
    (P extends keyof M ? M[P] : unknown) &
    (P extends K ? ReturnType<H[P]> : unknown)
  } : never : never;

您这样使用它:

type Test = MakeParam<House, "wood">;
/* type Test = {
    wood: Wood;
    tree: string;
} */

或对于多个键,像这样的联合:

type Test2 = MakeParam<House, "wood" | "nails">;
/* type Test2 = {
    wood: Wood;
    nails: number & Nail[];
    tree: string;
} */

注意number & Nail[]。那很奇怪而且没有用,但是正是您当前代码所需要的,所以您就可以了。假定您传递给nails()方法的对象不应具有名为nails的键。重复项将被相交;使用风险自负。

然后您可以像这样重构您的House定义:

class House {

  constructor() {
  }

  wood(i: { tree: string }): Wood {
    return {}
  }

  nails(i: { nails: number }): Nail[] {
    return [{}]
  }

  chair(i: MakeParam<House, "wood" | "nails">): Chair {
    return {}
  }

  diningRoom(i: MakeParam<House, "chair">): DiningRoom {
    return {}
  }

  livingRoom(i: MakeParam<House, "chair">): LivingRoom {
    return {}
  }

}

而且,它的工作原理与给定的代码相同。


我想您想对MakeParam<H, K>进行解释。这可能真的很罗word,所以我只给一个草图:

  • { [Q in K]: Parameters<H[Q]>[0] }[K] extends infer L ? ... : never

    这定义了L类型,它是K联合中命名的方法的所有参数的联合。当HHouseK"wood" | "nails"时,得到{ tree: string } | { nails: number }

  • { [Q in AllKeys<L>]: Extract<L, Record<Q, any>>[Q] } extends infer M ? ... : never

    这定义了一种类型M,该类型采用L并通过从所有联合件中提取所有属性将联合变成“交集”。当HHouse并且K"wood" | "nails"时,您将获得{ tree: string, nails: number }

  • { [P in K | keyof M]: (P extends keyof M ? M[P] : unknown) & (P extends K ? ReturnType<H[P]> : unknown) }

    这将创建一个具有M中所有属性的新对象,并且还将添加名称为K且类型为K命名的方法的返回类型的属性。通常,每个属性名称仅应出现在Kkeyof M中,并且如果我确定可以进行M[P] | ReturnType<H[P]>之类的事情(使用某些keyof检查以使该编译器完成),但是您的[ nails定义使我停顿了一下,我必须确保它的行为与您当前的行为相同,并出现有趣的number & Nail[]类型。


好的,希望能有所帮助。祝你好运!

Link to code

以上是关于减少使用特殊方法的课堂打字的主要内容,如果未能解决你的问题,请参考以下文章

typescript 打字稿+角度1的启动片段

json 打字稿片段

使用数组减少打字稿为累加器提供类型

为什么我不能在此片段中生成唯一对象数组?

laravel特殊功能代码片段集合

手机打字想要的字总是在后面怎么办