0

let's say I have a model definition like this.

export interface Basicdata {
    materialnumber: number;
    type: string;
    materialclass: string;
}

I furthermore have an array with values, which match exactly the order of the Basicdata model, i.e.

["10003084", "S", "CLIP"]

I am searching for a way to create the object from these values in the array. What I did is creating an empty object and assigning the array values.

const singleRow = rows[0];

const newBD: Basicdata = {
 materialnumber: 0,
 type: '',
 materialclass: '',  
}


newBD.materialnumber = singleRow[0];
newBD.type = singleRow[1];
newBD.materialclass = singleRow[2];

But surely there is a better, more elegant way to do that, no? I looked into map and reduce but could find a way.

Thank you.

Daniel
  • 3
  • 2
  • 2
    Have you tried using a class? – Michael T Jun 30 '22 at 19:03
  • 1
    Was just going to suggest the same thing. Classes allow you to create new instances of an object easily through the use of constructors. See also: https://www.typescriptlang.org/docs/handbook/2/classes.html – Major Productions Jun 30 '22 at 19:05
  • Does this answer your question? [What is the difference between an interface and abstract class?](https://stackoverflow.com/questions/1913098/what-is-the-difference-between-an-interface-and-abstract-class) – l -_- l Jun 30 '22 at 19:07
  • Thank you all for the prompt reply. I will look into classes. – Daniel Jun 30 '22 at 19:09

2 Answers2

1

As others have mentioned, use a class so that you can use the spread operator (technically you could create a function that returns an objects that meets the interface Basicdata, but you should use a class)

class Basicdata {
  materialnumber: number;
  type: string;
  materialclass: string;

  constructor(materialnumber: string | number, type: string, materialclass: string, ...rest: any) {
    this.materialnumber = typeof materialnumber === "number" ? materialnumber : parseInt(materialnumber);
    this.type = type;
    this.materialclass = materialclass;
  }
}

const rows: [string, string, string][] = [
  ["10003084", "S", "CLIP"],
  ["4324324", "B", "FOUR"],
  ["4444432", "C", "CORN"],
];

const singleRow = rows[0];

const newBD = new Basicdata(...singleRow) ;

Playground link

Samathingamajig
  • 11,839
  • 3
  • 12
  • 34
0

The issue with the following solution is that it relies on the order of the object properties being consistent. Is this about what you're looking for?

const singleRow = [1, "2", "3"];

const newBD: Basicdata = {
    materialnumber: 0,
    type: "",
    materialclass: "",
};

Object.keys(newBD).map((key, index) => {
    newBD[key] = singleRow[index]
});

If not, you could make a class as others have said, or you can make a helper function likes this, if it would help with your use case.

const addProps = (arr) => {
    const newObj = {
        materialnumber: arr[0],
        type: arr[1],
        materialclass: arr[2],
    };

    return newObj
};

addProps(singleRow)
Peter
  • 68
  • 6
  • This looked like what I was searching for, but I get an error @ newBD[key] Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Basicdata'. No index signature with a parameter of type 'string' was found on type 'Basicdata'.ts(7053) So most likely classes are the way to go. – Daniel Jun 30 '22 at 19:30
  • 1
    This isn't type-safe (notice the [tag:typescript] tag), you'd need to do a lot of work to make this be type-safe, if it's even possible with this method – Samathingamajig Jun 30 '22 at 19:37
  • That helper function also sounds neat. Would upvote you, but I am missing reputation, so take my thank you instead. – Daniel Jun 30 '22 at 19:39