简体   繁体   English

打字稿中的可选参数?

[英]optional parameters in typescript?

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. 使用常规JS,我通常会依赖falsey值来检查对象是否具有children属性。 But in Typescript is it best practice to initialise an empty array? 但在Typescript中最好初始化一个空数组? 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;
  }

}

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 : 或者,您也可以使用nullundefined的union:

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: data 不是 NavItem项的数组,为了得到你需要使用new关键字创建NavItem实例,例如:

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. 编译器不会抱怨这样做,因为typescript 基于结构子类型,并且这两种类型共享相同的结构。
But it's easy to see why it's wrong by adding methods to NavItem : 但是通过向NavItem添加方法很容易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 未捕获的TypeError:data [0] .getKey不是函数

You should even get a compilation error saying that getKey is missing in your array items. 你甚至应该得到一个编译错误,说你的数组项中缺少getKey

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

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 : 在@Zze发表评论后,我决定添加一个使用Object.assign “power”的简单构造函数:

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"
})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM