Add property to defined type in typescript

Viewed 26

I have this code:

const contacts = await this.prisma.contact.findMany({
  select: {
    id: true,
    name: true,
    mainSellerId: true,
    phone01: true

  }
})

And Prisma generates a custom type based on the parameters, like this:

const contacts: {
    id: number;
    name: string;
    mainSellerId: number;
    phone01: string;
}[]

I want to add the property lastMessage: string to the contacts array like this:

for (let i = 0; i < contacts.length; i++) {
  contacts[i].lastMessage = await findLastMessage(contacts[i])
}

Typescript will complain because there's no lastMessage property in contacts.

One solution is to create a new type and assign the contacts to another variable like this:

const losContacts: (typeof contacts[0] & { lastMessage?: string })[] = contacts

for (let i = 0; i < losContacts.length; i++) {
    losContacts[i].lastMessage = await findLastMessage(losContacts[i])
}

Another is to do this:

const findMany = () =>
    this.prisma.contact.findMany({
        select: {
            id: true,
            name: true,
            mainSellerId: true,
            phone01: true,
        },
    })

const contacts: (Awaited<ReturnType<typeof findMany>>[0] & { lastMessage?: string })[] = await findMany()

for (let i = 0; i < contacts.length; i++) {
    contacts[i].lastMessage = await findLastMessage(contacts[i])
}

But these options feel like to much effort...

Can I just, somehow, say somethig like:

const contacts = /* await this.prisma.contact.findMany ... */

contacts: AddPropertyOrSomething<{ lastMessage?: string }>

And for that line onward contacts will have another prop. Or something that doesn't require me to specify the object entirely, like this:

const contacts: { id: number; name: string; mainSellerId: number; phone01: string; lastMessage?: string }[] = await this.prisma.contact.findMany({
    select: {
        id: true,
        name: true,
        mainSellerId: true,
        phone01: true,
    },
})
1 Answers

Take advantage of spreading and map:

const contacts = await Promise.all((await this.prisma.contact.findMany({
  select: {
    id: true,
    name: true,
    mainSellerId: true,
    phone01: true
  }
})).map(async (contact, index) => ({
    ...concact,
    lastMessage: await findLastMessage(contacts[i])
})));

This is because { ...A, b: x } results in the type A & { b: x }.

Related