简体   繁体   English

Typescript自定义接口变量声明

[英]Typescript custom interface variable declaration

TypeScript novice here, and i'm currently learning the language on TutorialsPoint here . 这里是TypeScript的新手,我目前正在这里TutorialsPoint上学习该语言。 I'm currently having a hard time understanding the differences between these two pieces of code. 我目前很难理解这两段代码之间的区别。

interface Person{
    age: number;
}

interface Musician extends Person{
    instrument: string;
}

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

and

interface Person{
    age: number;
}

interface Musician extends Person{
    instrument: string;
}

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

What is the difference between the two? 两者有什么区别? and is there a specific situation where it is better to use the first/second implementation? 在特定情况下,使用第一种/第二种实现更好吗?

Thank you. 谢谢。

The examples are subtly different: 这些示例略有不同:

  • In the first, you're defining a variable with type Musician and then assigning an object to that variable which fits that type. 首先,您要定义一个类型为Musician的变量,然后将一个对象分配给适合该类型的变量。
  • In the second, you're defining a variable with no explicit type (which means that TypeScript will infer it), creating an empty object and then casting that object to type Musicican . 在第二个,您定义,没有明确的类型(这意味着打字稿会推断出它)一个变量,创建一个空的对象,然后铸造该对象类型Musicican
    • As an aside, the preferred syntax for casting in TypeScript is {} as Musician - the angle bracket syntax you're using isn't compatible with the JSX syntax extension commonly used with React applications, so it was replaced with something less ambiguous. 顺便说一句,在TypeScript中进行转换的首选语法是{} as Musician您使用的尖括号语法与React应用程序中常用的JSX语法扩展不兼容,因此已被模棱两可的东西所替代。

I would recommend the first example over the second in the vast majority of cases - an empty object doesn't really implement Musician , so you're effectively sidestepping the type checker there! 在绝大多数情况下,我会建议在第二个示例中使用第一个示例-空对象并没有真正实现Musician ,因此您实际上避开了类型检查器!

The one scenario in which you could make a case for using the second method would be if you have a Musician that starts empty and gets populated later on - in that case though, I think you'd be better off modelling that through the type definition itself by making the fields optional: 一个可以使用第二种方法的情况是,如果您有一个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;

This makes it clearer (both to you, other developers and the compiler) that there's cases where those fields will be undefined. 这使您(其他开发人员和编译器)都更加清楚,在某些情况下这些字段是不确定的。

They amount to the same thing in the end, but the former is preferred when possible. 最后,它们具有相同的含义,但在可能的情况下,首选前者。

In this case: 在这种情况下:

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

you are declaring that drummer is a Musician by using a type annotation , and assigning to it an object literal. 您通过使用类型注释并为其分配对象常量来宣布drummerMusician The compiler is happy about this because it can verify that yes, the object literal you're assigning is compatible with the Musician interface. 编译器对此很满意,因为它可以验证是的,您要分配的对象文字与Musician接口兼容。 It has an string-valued instrument property and a numeric-valued age property. 它具有字符串值的instrument属性和数字值的age属性。

Now what if we try this: 现在,如果我们尝试这样做:

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

The assignment of an empty object literal to a value declared as a Musician causes a compiler error. 将空对象文字分配给声明为Musician的值会导致编译器错误。 After all, an empty object literal does not have an string-valued instrument property or a numeric-valued age property. 毕竟,空对象文字不具有字符串值的instrument属性或数字值的age属性。 And you're being warned about that. 而且,您对此有所警告。 Now, you know that the next two lines will fix that problem, but the compiler doesn't. 现在, 知道接下来的两行将解决该问题,但是编译器无法解决。

So you can change it to use a type assertion instead of a type annotation: 因此,您可以将其更改为使用类型断言而不是类型注释:

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

The assertion is where you tell the compiler "this object is really a Musician , even though right now it doesn't look like it." 断言就是告诉编译器“此对象实际上是Musician ,即使现在看起来并不像它。” You're taking on the responsibility of ensuring that drummer is a Musician and relieving the compiler of the responsibility of verifying that for you. 您有责任确保drummerMusician并让编译器免除了为您验证的责任。

And since the next two lines add the required properties, everything is fine. 并且由于接下来的两行添加了必需的属性,所以一切都很好。


The former is preferable because you usually want the compiler to verify your types if it can. 前者是可取的,因为您通常希望编译器在可能的情况下验证您的类型。 A type assertion gives up some safety, which is fine until it isn't, like driving an automobile without a seat belt: 类型断言放弃了一些安全性,直到没有安全为止,这就像在没有安全带的情况下驾驶汽车一样:

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

There are times when you have to use type assertions. 有时您必须使用类型断言。 For example, when you have some kind of circular reference where you need to build the object in pieces: 例如,当您需要某种循环引用时,您需要分段构建对象:

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

In the above, each MarriedPerson needs a reference to a MarriedPerson ... but there won't be one until you've created one. 在上面,每个MarriedPerson需要一个参考MarriedPerson ...但不会有一个你创建一个到。 So you are forced to resort to having a short period of time where one of the MarriedPerson objects does not have the required spouse . 因此,您不得不在很短的时间内MarriedPerson对象之一没有所需spouse And thus assertions are required. 因此需要断言。

Does that make sense? 那有意义吗? Hope it helps; 希望能帮助到你; good luck! 祝好运!

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

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