打字稿中的可选参数?

Ric*_*d G 7 typescript

刚刚在角度上下文中打字.您可以在下面的示例中将属性标记为可选吗?您如何建议指定导航项目没有孩子?使用常规JS,我通常会依赖falsey值来检查对象是否具有children属性.但在Typescript中最好初始化一个空数组?那些可能/可能没有值的其他原始属性呢?

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;
  }

}
Run Code Online (Sandbox Code Playgroud)

Nit*_*mer 15

是的,将属性标记为可选项非常容易,您可以?在其后添加:

class NavItem {
  key: string;
  text: string;
  target: string;
  children?: NavItem[];
}
Run Code Online (Sandbox Code Playgroud)

或者,您也可以使用和null或undefined:

class NavItem {
  key: string;
  text: string;
  target: string;
  children: NavItem[] | undefined;
}
Run Code Online (Sandbox Code Playgroud)

话虽如此,你误解了一些非常重要的东西,这是错误的:

const data: NavItem[] = [
  {
    key: "dashboard",
    target: "dashboard",
    text: "Dashboard",
    children: []
  },
  {
    key: "sales",
    target: "sales",
    text: "Sales"
  }
];
Run Code Online (Sandbox Code Playgroud)

data是不是数组NavItem的项目,才能得到你需要创建的实例NavItem使用的new关键字,例如:

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

编译器不会抱怨这样做,因为typescript 基于结构子类型,并且这两种类型共享相同的结构.
但是通过添加方法很容易理解为什么它是错误的NavItem:

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

  getKey() {
    return this.key;
  }
}
Run Code Online (Sandbox Code Playgroud)

现在尝试使用您的代码:

console.log(data[0].getKey());
Run Code Online (Sandbox Code Playgroud)

而你最终会得到:

未捕获的TypeError:data [0] .getKey不是函数

您甚至应该收到编译错误,说明getKey数组项中缺少该错误.

如果您只打算NavItem用作数据对象那么它并不重要,但您应该只使用接口或类型别名,因为它们不会被编译为js并且您可以避免冗余内存使用:

interface NavItem {
  key: string;
  text: string;
  target: string;
  children?: NavItem[];
}
Run Code Online (Sandbox Code Playgroud)

编辑

在@Zze发表评论后,我决定添加一个使用"权力"的简单构造函数Object.assign:

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

  constructor(data?: NavItem) {
      if (data) {
          Object.assign(this, data);
      }
  }
}
Run Code Online (Sandbox Code Playgroud)

然后:

new NavItem({
    key: "sales",
    target: "sales",
    text: "Sales"
})
Run Code Online (Sandbox Code Playgroud)