简体   繁体   中英

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. In this code I'm creating the Person interface.

Then, I'm creating a person 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. 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"

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 .

That said, the technique could be useful if you're dealing with a more complex object, such as

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.

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

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

will also result in the object type being automatically inferred. (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 )

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. So this is very much about expression and communication, not about functionality - as you say me: string would be equivalent (for now). It tells the reader that the variable me is going to be used like the name of a Person.

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. 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 .

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.

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.

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. You don't have to specify let name: string , or let 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. You should not define it constantly everywhere.

Remember, if you do let test = "something" , typescript knows this is a string. You don't need to define type always, just where they are needed:)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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