Home > Mobile >  hasOwnProperty always returns false on object with variable properties
hasOwnProperty always returns false on object with variable properties

Time:12-05

I'm consuming some k8s objects with typescript and my json looks like this:

{
 "startTime": "2022-12-01T19:15:58Z",
  "taskRuns": {
     "task1": {
        "pipelineTaskName": "task1Ref",
         "status": {
             "completionTime": "2022-12-01T19:17:27Z",
              "conditions": [
                 {
                   "lastTransitionTime": "2022-12-01T19:17:27Z",
                   "message": "",
                   "reason": "TaskRunImagePullFailed",
                   "status": "False",
                   "type": "Succeeded"
                  }
               ]}},
   "task2":{same fields as task1},
   "task3": {same}
}}

I also have an array with the TaskRun names which looks like the following:

["task1","task2",....]

The relevant interface for the object above looks like:

export interface PipelineRunStatus {
  startTime: string;
  taskRuns: Truns;
}
export interface Truns {
  [key: string]: TaskRun;
}
export interface TaskRUn {<fields from above>}

I'm trying to match the array elements to the variable task keys in a taskrun and extract information with the code below:

    type taskRunKey = keyof typeof currentRun.Status.taskRuns
    //taskRuns is my string array
     taskRuns.map((taskRunName: string) => {
     console.log(taskRunName)

     if (currentRun?.Status?.taskRuns?.hasOwnProperty(taskRunName as taskRunKey))
          console.log(currentRun.Status?.taskRuns[taskRunName as status?.conditions[0])
      else {
          console.log(currentRun?.Status?.taskRuns)
          console.log(currentRun?.Status)
       }

but this prints

task1
undefined
Object { TaskRuns: {… task1:{..the object above...}}}
​
task2
undefined
Object { TaskRuns: {… pretty much the object above...}}
​

etc

In short: the code above always ends up in the "else" branch of the statement despite the fact that there is an object property with the correct name that matches. Can someone please explain what am I missing?

CodePudding user response:

It looks like you're using the map() method on taskRuns, but taskRuns isn't an array. It's an object, and the map() method only works on arrays.

To fix this, you can use a regular for loop to iterate over the keys of taskRuns like this:

for (let taskRunName in currentRun?.Status?.taskRuns) {
  console.log(taskRunName)

  if (currentRun?.Status?.taskRuns?.hasOwnProperty(taskRunName as taskRunKey))
    console.log(currentRun.Status?.taskRuns[taskRunName as status?.conditions[0])
  else {
    console.log(currentRun?.Status?.taskRuns)
    console.log(currentRun?.Status)
  }
}

Alternatively, you could use the Object.keys() method to get an array of keys from currentRun.Status.taskRuns, and then use the map() method on that array.

Object.keys(currentRun?.Status?.taskRuns).map((taskRunName: string) => {
  console.log(taskRunName)

  if (currentRun?.Status?.taskRuns?.hasOwnProperty(taskRunName as taskRunKey))
    console.log(currentRun.Status?.taskRuns[taskRunName as status?.conditions[0])
  else {
    console.log(currentRun?.Status?.taskRuns)
    console.log(currentRun?.Status)
  }
})

I hope this helps! Let me know if you have any other questions.

CodePudding user response:

Turns out I had a few things wrong:

  1. Typo in "taskRuns" it should be "TaskRuns" and typescript for some reason doesn't deserialise JSON case insensitive (like golang does). I changed my types to be export interface PipelineRunStatus { startTime: string; TaskRuns: Truns; }
  2. hasOwnProperty is incorrect, I needed instead : Object.keys(currentRun?.Status?.TaskRuns).includes(taskRunName)

Thank you everyone who spent time on this!

  • Related