Home > OS >  Assigning to object field with typescript
Assigning to object field with typescript

Time:03-07

I have two objects of the same interface:

interface Project {
  _id?: string
  title: string
  description: string
  goal: string
  tasks?: Task[]
  createdAt?: Date
  updatedAt?: Date
}

One contains all the above fields and the other should contain some or all of this: title / description / goal.

I want to assign from second to the first only for the relevant key and only if there is a valid value.

what I got so far:

const updateProjectUtil = (target: Project, update: Project): Project => {
  Object.keys(update).forEach(key => {
    const k = key as keyof Project;
    if (target.hasOwnProperty(k) && update[k]) {
      target[k] = update[k] // this line get a typescript error 
    }
  })
  return target;
}

I am getting an error:

Type 'string | Task[] | Date | undefined' is not assignable to type 'string & Task[] & Date'. Type 'undefined' is not assignable to type 'string & Task[] & Date'. Type 'undefined' is not assignable to type 'string'.

I tried using Object.entries but it doesn't seem to have any effect.

The bigger picture: I am using Node.js and Express to build a RESTful API. This belongs to the controller of the update route which get the update object from the client side and the target object from the db (MongoDB), changes what fields it needs and returns the data to the client side after saving to the db.

What can I do to make it work? Thanks.

CodePudding user response:

Try

interface Project {
  [key: string]: unknown // indexable
  _id?: string
  title: string
  description: string
  goal: string
  tasks?: Task[]
  createdAt?: Date
  updatedAt?: Date
}

I think this is missing an index signature.

CodePudding user response:

When I was trying to run your code, I got another error. Not sure if it's a mistake in your question, but the code below works on my side:

type Task = {
  name: string
}

interface Project {
  _id?: string
  title: string
  description: string
  goal: string
  tasks?: Task[]
  createdAt?: Date
  updatedAt?: Date
}

const updateProjectUtil = (target: Project, update: Project): Project => {
  let result = { ...target }

  Object.keys(update).forEach(key => {
    const k = key as keyof Project;
    const updatingValue = update[k]
    if (target.hasOwnProperty(k) && updatingValue) {
      result = { ...result, [k]: updatingValue }
    }
  })
  return result;
}

I also changed the function to not modify the input parameter target, since you return it anyway

  • Related