[SOLVED] Add property to defined type in typescript

Issue

This Content is from Stack Overflow. Question asked by Lucas Steffen

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,
    },
})



Solution

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 }.


This Question was asked in StackOverflow by Lucas Steffen and Answered by caTS It is licensed under the terms of CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.

people found this article helpful. What about you?