简体   繁体   English

将变量类型声明为接口的属性有什么用处(在打字稿中)

[英]What's the usefulness in declaring a variable type as the property of an interface (in typescript)

I'm new to typescript, and I'm trying to understand the usefulness of the code below.我是 typescript 的新手,我正在尝试了解以下代码的用处。 In this code I'm creating the Person interface.在这段代码中,我创建了Person接口。

Then, I'm creating a person john .然后,我正在创建一个人john This part makes a lot of sense.这部分很有意义。 We're defining an interface, and then we're creating a variable that conforms to that predefined interface.我们正在定义一个接口,然后我们正在创建一个符合该预定义接口的变量。 I can see the usefulness of this.我可以看到这个的用处。

However, in the last line, we're setting the type as the name property of the Person interface.但是,在最后一行中,我们将类型设置为Person接口的name属性。 I've seen code like this in the wild, and I can't get my head around what's going on.我在野外看到过这样的代码,但我无法理解发生了什么。

How is this different than just saying: let me: string = "karl"这与仅仅说: let me: string = "karl"有何不同

interface Person {
  name: string;
  hungry: boolean;
}

let john: Person = {
    name: "john",
    hungry: false
}

let me: Person["name"] = "karl"

For the code in the question - you're right, it doesn't make much sense.对于问题中的代码 - 你是对的,它没有多大意义。 Person["name"] is unnecessarily obtuse compared to just string . Person["name"]string相比不必要地迟钝。

That said, the technique could be useful if you're dealing with a more complex object, such as也就是说,如果您要处理更复杂的 object,该技术可能会有用,例如

interface Person {
  name: string;
  hungry: boolean;
  someProp: {
    subProp1: number;
    subProp2: string;
    subProp3: Array<string>
  }
}

Say you wanted the type of the subProp - you could then use Person["someProp"] , which would be much less repetitive than listing out the full type of the nested object again.假设您想要subProp的类型 - 然后您可以使用Person["someProp"] ,这比再次列出嵌套 object 的完整类型要少得多。

const somePropToAssignToPerson: Person["someProp"] = {
  subProp1: 5,
  subProp2: 'foo',
  subProp3: ['bar']
};

is arguably nicer than可以说比

const somePropToAssignToPerson: {
  subProp1: number;
  subProp2: string;
  subProp3: Array<string>
} = {
  subProp1: 5,
  subProp2: 'foo',
  subProp3: ['bar']
};

That said, note that none of this deliberate annotation is necessary in the vast majority of cases you'll encounter.也就是说,请注意,在您将遇到的绝大多数情况下,这些刻意的注释都不是必需的。 Doing just只是做

let me = "karl"

will have TypeScript properly infer it as a string , and将 TypeScript 正确地推断为string ,并且

const somePropToAssignToPerson = {
  subProp1: 5,
  subProp2: 'foo',
  subProp3: ['bar']
};

will also result in the object type being automatically inferred.还将导致自动推断出 object 类型。 (If you make a mistake while declaring such an object, TypeScript will throw an error if you ever try to assign it to a .someProp ) (如果你在声明这样一个 object 时犯了错误,如果你试图将它分配给.someProp TypeScript 将会抛出错误)

If you're ever going to change the type of Person["name"] from string to something else (eg type Name = {given: string; family: string} ), then you'll have to change it only in a single place and you'll remember to update the me variable, instead of keeping me: string which may be undesirable.如果您打算将Person["name"]的类型从string更改为其他类型(例如type Name = {given: string; family: string} ),那么您只需一次性更改它放置,你会记得更新me变量,而不是保留me: string这可能是不受欢迎的。 So this is very much about expression and communication, not about functionality - as you say me: string would be equivalent (for now).所以这在很大程度上是关于表达和交流,而不是关于功能——正如你对me: string是等价的(目前)。 It tells the reader that the variable me is going to be used like the name of a Person.它告诉读者变量me将被用作一个人的名字。

It might similarly make sense to write写起来可能同样有意义

type Name = string;
interface Person {
  name: Name;
  hungry: boolean;
}

let john: Person = {
    name: "john",
    hungry: false,
};

let me: Name = "karl";

where the type of Person-names is given an explicit name already.其中已经为 Person-names 类型指定了明确的名称。 Sometimes, there's not much advantage in a separate name, and it makes as much sense to refer to the type Person["name"] as it does to refer to a type PersonName .有时,单独的名称并没有多大优势,引用类型Person["name"]与引用类型PersonName一样有意义。

In many cases declaring the type this way may not be the best practice.在许多情况下,以这种方式声明类型可能不是最佳做法。

As others mentioned, an advantage would be that if you change it in one place (interface), it'll be changed in the object below as well.正如其他人提到的那样,一个优点是如果您在一个地方(接口)更改它,它也会在下面的 object 中更改。

However, a disadvantage is that you would bloat your code with unnecessary type definitions.然而,一个缺点是你会用不必要的类型定义来膨胀你的代码。

For example, if you have already created Person interface, and you marked name: string, you don't need to do always worry about mentioning a type.例如,如果你已经创建了 Person 接口,并且你标记了 name: string,你就不需要总是担心提到一个类型。

If you want to create a new person, make it like:如果您想创建一个新人,请将其设置为:

let person: Person = {
    name: "John",
    hungry: true,
}

Now, if you need to get name, for example, do现在,如果你需要得到名字,例如,做

let name = person.name;

TypeScript will by default know that name is String. TypeScript 默认知道名称是字符串。 You don't have to specify let name: string , or let name: Person["name"] .您不必指定let name: stringlet name: Person["name"] It just adds an extra layer of complexity that will not help you in any way and will make your code much more unreadable and harder to understand.它只是增加了一层额外的复杂性,不会以任何方式帮助您,并且会使您的代码更加难以阅读和理解。

The point of declaring an interface is to declare types of data the object will contain.声明接口的目的是声明 object 将包含的数据类型。 You should not define it constantly everywhere.你不应该在任何地方不断地定义它。

Remember, if you do let test = "something" , typescript knows this is a string.请记住,如果您执行let test = "something" , typescript 就会知道这是一个字符串。 You don't need to define type always, just where they are needed:)您不需要总是定义类型,只需在需要的地方定义类型即可:)

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

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