optional parameters in typescript?

typescript

Solution

Yeah, it's very easy to mark a property as optional, you add `?` after it:

class NavItem {
  key: string;
  text: string;
  target: string;
  children?: NavItem[];
}

Alternatively you can also use a union with `null` or `undefined`:

class NavItem {
  key: string;
  text: string;
  target: string;
  children: NavItem[] | undefined;
}

With that being said, you misunderstood something very important, this is wrong:

const data: NavItem[] = [
  {
    key: "dashboard",
    target: "dashboard",
    text: "Dashboard",
    children: []
  },
  {
    key: "sales",
    target: "sales",
    text: "Sales"
  }
];

`data` is not an array of `NavItem` items, in order to get that you'll need to create instances of `NavItem` using the `new` keyword, for example:

const data: NavItem[] = [
  Object.assign(new NavItem(), {
    key: "dashboard",
    target: "dashboard",
    text: "Dashboard",
    children: []
  }),
  Object.assign(new NavItem(), {
    key: "sales",
    target: "sales",
    text: "Sales"
  })
];

The compiler doesn't complain about doing that because typescript is based on structural subtyping and the two types share the same structure. But it's easy to see why it's wrong by adding methods to `NavItem`:

class NavItem {
  key: string;
  text: string;
  target: string;
  children?: NavItem[];

  getKey() {
    return this.key;
  }
}

Now try this with your code:

console.log(data[0].getKey());

And you'll end up with:

Uncaught TypeError: data[0].getKey is not a function

You should even get a compilation error saying that `getKey` is missing in your array items.

If you only intend to use `NavItem` as data objects then it doesn't really matter, but you should just use interfaces or type aliases instead as they don't get compiled to js and you avoid redundant memory usage:

interface NavItem {
  key: string;
  text: string;
  target: string;
  children?: NavItem[];
}

Edit

After a comment from @Zze I've decided to add a simple constructor that uses the "power" of `Object.assign`:

class NavItem {
  key: string;
  text: string;
  target: string;
  children?: NavItem[];

  constructor(data?: NavItem) {
      if (data) {
          Object.assign(this, data);
      }
  }
}

then:

new NavItem({
    key: "sales",
    target: "sales",
    text: "Sales"
})

Problem

Just new to typescript in an angular context. Can you mark properties as optional in the example below? How would you recommend specifying a nav item has no children? With regular JS I would usually rely on a falsey value to check if the object has `children` property. But in Typescript is it best practice to initialise an empty array? What about other primitive properties that may/may not have values? ``` import { Injectable } from '@angular/core'; export class NavItem { key: string; text: string; target: string; children: NavItem[]; } const data: NavItem[] = [ { key: "dashboard", target: "dashboard", text: "Dashboard", children: [] }, { key: "sales", target: "sales", text: "Sales" } ]; @Injectable() export class NavService { getNav() { return data; } } ```

Original source