Typescript 动态对象 return 基于数组参数的类型

Typescript dynamic object return type based on array parameter

通过以下抽象,我可以调用此方法,return 类型基于我传递给它的基于字符串的字段,如下所示。

abstract class Entity {
  abstract id: string
}

class User extends Entity {
  constructor(obj: Partial<User>) {
    super()
    Object.assign(this, obj)
  }

  id: string
  name: string
  age: number
}

class Post extends Entity {
  constructor(obj: Partial<Post>) {
    super()
    Object.assign(this, obj)
  }

  id: string
  content: string
  time: Date
}


export const useSyncFields = <T extends Entity, U extends (keyof T & string)[]>(
  type: { new(obj: T): T },
  id: string,
  fields: U,
): { [K in U[number]]: T[K] } => {
   ...
}

const user1: {id: string, name: string} = useSyncFields(User, "1234", ["id", "name"])
const user2: {id: string, age: number} = useSyncFields(User, "1234", ["id", "age"])
const post: {content: string} = useSyncField(Post, "4567", ["content"]
// etc

通过使用类型参数 <T extends Entity, U extends (keyof T & string)[] 和 return 类型 { [K in U[number]]: T[K] },从 Typescript 推断的 return 类型“正确”,但 VSCode或 WebStorm 在正确推断类型方面做得非常出色。

我觉得有一组更好的类型参数/return 类型可以更好地推断。我所拥有的真的是我能在这里做的最好的吗?或者是否有某种类型的忍者可以指导我找到更好的解决方案?

如果你只是想让这个更简单,我会选择:

export const useSyncFields = <T extends Entity, U extends keyof T>(
  type: { new(obj: T): T },
  id: string,
  fields: U[],
): Pick<T, U> => {
   return {} as any // implementation
}

如果您不关心类型中数组的长度或顺序,则不需要对整个数组进行泛型处理。所以这仅对 fields 数组的成员通用。这意味着你不必去钓鱼 U[number] 来获得键的联合。

它还使用 the Pick utility type,这样您就可以避免复杂的外观映射 return 类型。

Playground