2

I have a class and then defined an array of class, each time that I want to add a node to array, I have to mention the class name that I don't like it:

export class ItemModel {
  constructor(
    ID,
    Name
  ) {
    this.ID = ID;
    this.Name = Name; 
  }
}

export var ItemsArray = [];

ItemsArray.push(new ItemModel(0, "BreakFast"));
ItemsArray.push(new ItemModel(1, "Lunch"));
ItemsArray.push(new ItemModel(2, "Dinner"));

After reading this post:

https://answers.unity.com/questions/637902/how-to-use-javascript-array-with-classes.html

I tried to declare the class at the time that I define the array like this:

var ItemsArray : ItemModel[];

but I get error : "Types Can only be used in .ts files.

I searched google for that but none of them was helpful.

Any recommendation would be appreciated.

albert sh
  • 1,095
  • 2
  • 14
  • 31
  • javascript's arrays aren't strongly typed. you could add a function that hides the construction and pushing. – Daniel A. White May 30 '19 at 15:05
  • `var PanelItemsArray : PanelItem[];` is TypeScript syntax and you need a TypeScript compiler to turn it back to JavaScript. But even then, you don't solve your basic problem, since even in TS you'd need to do `ItemsArray.push(new PanelItem(0, "BreakFast"));` - all TS would provide you with is an error if you have `ItemsArray.push(42);` in your code, since `42` is a number, and not `ItemModel` – VLAZ May 30 '19 at 15:07
  • @T.J.Crowder, Sorry It was because of copying parts of my source, I edited that – albert sh May 30 '19 at 15:15

2 Answers2

3

The post you've linked to is using TypeScript, which is a different language from JavaScript: It's a superset of JavaScript (which compiles to JavaScript) that adds static typing (and a couple of other features, like automatic property initialization in constructors).

This TypeScript line:

var ItemsArray : ItemModel[];

is equivalent to this JavaScript:

var ItemsArray;

It's just that the TypeScript version declares that the ItemsArray variable has the static type ItemModel[].

If you're using JavaScript itself, you don't define the types of variables. Your export var ItemsArray = []; is just fine (other than that I'd use let or const instead of var).


Side Note: You can write that array more concisely in JavaScript using an array initializer:

export const ItemsArray = [
    new ItemModel(0, "BreakFast"),
    new ItemModel(1, "Lunch"),
    new ItemModel(2, "Dinner")
];

That's also valid TypeScript, even without a type declaration: TypeScript will infer that you want the type of ItemsArray to be ItemModel[] (because TypeScript does type inference and it can see that you're filling ItemsArray with ItemModel objects).

If you wanted to start with an empty array but still give it a static type, you'd do this:

//                                   /------ Telling TypeScript to use ItemModel[]
//                      vvvvvvvvvvvvv        as the type
export const ItemsArray : ItemModel[] = [];
//                                   ^^^^^-- Initializing ItemsArray with an
//                                           empty array

Then your push calls would be typechecked, so this would work:

ItemsArray.push(new ItemModel(0, "BreakFast"));

but this would cause an error (during TypeScript->JavaScript compilation)

ItemsArray.push("BreakFast");

because "Breakfast" is not compatible with ItemModel.


Side Note 2: The overwhelming convention in JavaScript (and TypeScript) is that variables start with a lowercase letter, not an uppercase one. So itemsArray rather than ItemsArray.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Thanks for your comment and sorry for my edits after your answer, I has mistakenly used PanelItem in parts of above sample code and I changed it to ItemModel later. You are right , I am using react type script.I cant use array initializer as nodes will be added at run time after user actions. – albert sh May 30 '19 at 15:24
  • 1
    @albertsh - I've updated the answer to handle the change in the question (and also to address the issue of not being able to add the entries until later, though that was a bit of a coincidence :-) ). – T.J. Crowder May 30 '19 at 15:25
  • 1
    Appreciate for your time and advices ;) – albert sh May 30 '19 at 15:50
2

Another alternative is to create a class that holds your items and make a method to add/remove them. This way, you won't have to new up your array items everytime. ...Well, you will. You just don't have to do it, the code will.

class ItemModel {
  constructor(id, name) {
    this.id = id;
    this.name = name;
  }
}

class ItemModelCollection {
  constructor() {
    this.items = [];
  }
  addItem(id, name) {
    if (Array.isArray(this.items)) {
      this.items.push(new ItemModel(id, name));
    }
  }
  removeItem(id) {
    if (Array.isArray(this.items)) {
      this.items = this.items.filter( i => i.id !== id);
    }
  }
}

const itemCollection = new ItemModelCollection();
document.getElementById('addItem').onclick = (e) => {
  const id = itemCollection.items.length; // obviously figure out a better id generator
  itemCollection.addItem(id, `Item Number ${id}`);
  console.log(itemCollection);
};
<button id="addItem">Add Item</button>

I should also note that not doing new ItemModel(id, name) and doing the mentioned typescript way (<ItemModel>{ id: id, name: name}) is fine, but if the class has methods, they will not work since you are not 'newing it up'. If you just set the properties without initializing the class, you essentially lose the point of having the class.

Related/Explantion for the pattner/issues with classes (not really angular specific like the article says): Angular : Class and Interface

mwilson
  • 12,295
  • 7
  • 55
  • 95