Typescript自定义接口变量声明

时间:2018-05-09 19:04:26

标签: angular typescript declaration

这里是TypeScript新手,我目前正在TutorialsPoint here上学习该语言。 我目前很难理解这两段代码之间的差异。

interface Person{
    age: number;
}

interface Musician extends Person{
    instrument: string;
}

var drummer:Musician = {
    instrument: "drum",
    age: 28
}

interface Person{
    age: number;
}

interface Musician extends Person{
    instrument: string;
}

var drummer = <Musician>{}
drummer.instrument = "drum"
drummer.age = 28

两者有什么区别?是否存在使用第一个/第二个实施更好的特定情况?

谢谢。

2 个答案:

答案 0 :(得分:0)

这些例子略有不同:

  • 首先,您要定义一个类型为Musician的变量,然后将一个对象分配给适合该类型的变量。
  • 在第二种情况下,您要定义一个没有显式类型的变量(这意味着TypeScript会推断它),创建一个空对象,然后投射该对象以键入Musicican
    • 另外,在TypeScript中进行强制转换的首选语法是{} as Musician - 您使用的尖括号语法与React应用程序常用的JSX语法扩展不兼容,因此它被替换为某些东西不那么暧昧。

我会在绝大多数情况下推荐第一个例子 - 空对象并没有真正实现Musician,所以你有效地回避那里的类型检查器!

您可以使用第二种方法设置案例的一种情况是,如果您的Musician开始为空并且稍后会填充 - 在这种情况下,我认为您会更好通过使字段可选来通过类型定义本身进行建模:

interface Person {
    // '?' makes a field optional 
    age?: number;
}

interface Musician extends Person {
    instrument?: string;
}

// The cast can now be replaced with a proper type
var drummer: Musician = {};
drummer.instrument = "drum";
drummer.age = 28;

这使得(对于您,其他开发人员和编译器)更加清楚,在某些情况下,这些字段将是未定义的。

答案 1 :(得分:0)

它们最终相同,但前者在可能的情况下是首选。

在这种情况下:

var drummer: Musician = {
    instrument: "drum",
    age: 28
}

您通过使用type annotation声明drummerMusician,并为其指定了一个对象字面值。编译器对此感到高兴,因为它可以验证是,您分配的对象文字与Musician接口兼容。它具有字符串值instrument属性和数值age属性。

现在如果我们尝试这个怎么办:

var drummer: Musician = {};
//  ~~~~~~~ <-- error!
// Type '{}' is not assignable to type 'Musician'.
//  Property 'instrument' is missing in type '{}'.
drummer.instrument = "drum"
drummer.age = 28

将空对象文字赋值为声明为Musician的值会导致编译器错误。毕竟,空对象文字没有字符串值instrument属性或数值age属性。而且你被警告了。现在,知道接下来的两行将解决这个问题,但编译器没有。

因此,您可以将其更改为使用type assertion而不是类型注释:

var drummer = <Musician>{}; // okay
drummer.instrument = "drum"
drummer.age = 28

断言是你告诉编译器“这个对象真的是Musician的地方,即使它现在看起来不像它。”您承担的责任是确保drummerMusician,并使编译者免除为您验证的责任。

由于接下来的两行添加了所需的属性,一切都很好。

前者是首选,因为您通常希望编译器验证您的类型。一种类型的断言放弃了一些安全性,这种情况很好,直到没有安全带,就像驾驶没有安全带的汽车一样:

var drummer = <Musician>{}; // okay
drummer.age = 28;
// whoops, forgot the instrument, but TypeScript isn't complaining

// ... later ...
console.log(drummer.instrument.toUpperCase()); 
// no error at compile time
// but blows up at runtime

有时您必须使用类型断言。例如,当您需要某种循环引用时,需要将这些对象分段构建:

interface MarriedPerson extends Person {
  spouse: MarriedPerson
}

var adam: MarriedPerson = {
  age: 0,
  // spouse: eve <-- can't do this before eve is defined
} as MarriedPerson;

var eve: MarriedPerson = {
  age: 0,
  spouse: adam
}

adam.spouse = eve;  // okay now

在上文中,每个MarriedPerson都需要对MarriedPerson的引用...但在创建之前不会有一个MarriedPerson。因此,您被迫使用其中一个spouse对象没有所需flex-growth的短时间。因此需要断言。

这有意义吗?希望能帮助到你;祝你好运!