如何动态键入从另一个对象创建对象的函数?

时间:2019-07-27 17:20:02

标签: typescript object prisma

我正在尝试使用我首先用Javascript编写的递归函数从源对象创建新对象。在另一个项目中,我想重用该函数,但在那里我使用TypeScript,如果可以键入输出对象,那将是很好的选择,但我不知道要完成此操作。该功能旨在将使用Prisma的GraphQL服务器的响应转换为服务器用来更新或创建条目的任何模型的UpdateInput。

我现在拥有的是这个,但是它将返回不是我想要的任何类型。

type Mode = 'create' | 'update' | 'delete' | 'connect' | 'disconnect'

function toPrismaObject<Source>(mode: Mode, source: Source, exception: { [key: string]: Mode } = {}, extras: any = {}): any {
  if (Array.isArray(source)) {
    return source.map((item) => toPrismaObject(mode, item, exception))
  }
  const newObject = { ...source }
  Object.entries(newObject).forEach(([key, value]) => {
    if (value !== null && (Array.isArray(value) || typeof value === "object")) {
      if (exception[key]) {
        Object.assign(newObject, { [key]: { [exception[key]]: toPrismaObject(mode, value, exception) } })
      } else {
        Object.assign(newObject, { [key]: { [mode]: toPrismaObject(mode, value, exception) } })
      }
    }
  })
  return { ...newObject, ...extras }
}

const source = {
  name: "John Doe",
  dog: {
    name: "Boomer"
  },
  address: {
    street: "Sample street",
    number: 14
  },
  children: [
    { id: "some_id" },
    { id: "some_id" }
  ]
}

const res = toPrismaObject("update", source, { children: "connect" })

console.log(res) /*

{
  name: "John Doe",
  dog: {
    update: {
      name: "Boomer"
    }
  },
  address: {
    update {
      street: "Sample street",
      number: 14
    }
  },
  children: { 
    connect: [
       { id: "some_id" },
       { id: "some_id" }
    ]
  }
}

*/

我希望动态地生成结果对象,因此一旦将其用作函数中的参数,就可以知道类型是否与该函数的参数类型匹配。我到处看,但找不到类似的问题/答案。此函数产生的类型应如下所示:

type ResultingType = {
  name: string
  dog: { update: { name: string } }
  address: { update: { street: string, number: number } }
  children: { connect: { id: string }[] }
}

谢谢您的帮助。

0 个答案:

没有答案