Limit the value range of object key name in typescript
Liu wayong 2021-06-04 10:49:30

When we use TypeScript when , We want to use the type system it provides to limit all aspects of the code , The key value of the object , No exception .

For example, we have an object to store the names of people in each grade , The type looks like this :

type Students = Record<string, string[]>;
 

Of course , That's what data looks like :

const students: Students = {
Freshman: ["David", "John"],
sophomore: [],
Junior: ["Lily"],
Senior: ["Tom"],
};
 

Restrict the object key name to enumeration

The problem with the above data types is , Grade is limited, several kinds of value can take , And you can add any attribute to this object , So the data is not pure enough .

So we add enumeration , List the desirable values :

export enum Grade {
Freshman,
sophomore,
Junior,
Senior,
}
 

Now? , Just limit the key name of the object to the above enumeration .

- type Students = Record<string, string[]>;
+ type Students = Record<Grade, string[]>;
 

So our data can be written like this :

const students: Students = {
[Grade.Freshman]: ["David", "John"],
[Grade.sophomore]: [],
[Grade.Junior]: ["Lily"],
[Grade.Senior]: ["Tom"],
// Object literal may only specify known properties, and 'blah' does not exist in type 'Students'.ts(2322)
blah: ["some one"],
};
 

such , Limits the range of key names on objects , You can see that if you add a key other than enumeration, an error will be reported .

More semantic enumeration values

But there is something wrong with the above , Because the enumeration value is from 0 The starting number , such , As a key value is not semantic enough , This is reflected in accessing the properties of an object :

1

Fixed our enumeration , Use more semantic text as its value :

export enum Grade {
Freshman = "Freshman",
sophomore = "sophomore",
Junior = "Junior",
Senior = "Senior",
}
 

When you use the enumeration again , It's not meaningless numbers .

2

If you will , Enumeration values can also be in Chinese ,

export enum Grade {
Freshman = " A freshman ",
sophomore = " Sophomore ",
Junior = " Junior Girl ",
Senior = " Senior driver ",
}
 

There is no problem when using it :

3

Key value optional

There's another problem with the type definition above , namely , It requires that when used, the object contains all the values in the enumeration , such as sophomore No one in this grade , Don't write , But it will report a mistake .

// Property 'sophomore' is missing in type '{ Freshman: string[]; Junior: string[]; Senior: string[]; }' but required in type 'Students'.ts(2741)
const students: Students = {
[Grade.Freshman]: ["David", "John"],
// [Grade.sophomore]: [],
[Grade.Junior]: ["Lily"],
[Grade.Senior]: ["Tom"],
};
 

therefore , The optimization type is optional :

type Students = Partial<Record<Grade, string[]>>;
 

Restrict the key name of an object to the value in the array

If the optional value is not defined by enumeration , It comes from an array ,

const grades = ["Freshman", "sophomore", "Junior", "Senior"];
 

This means that we need to extract the values from the array to form a union type .

The first use of const assertions Turn an array into a tuple (Tuple) type ,

const grades = <const>["Freshman", "sophomore", "Junior", "Senior"];
 

recycling typeof and Lookup Types Get the final union type :

// For the actual type Keys = "Freshman" | "sophomore" | "Junior" | "Senior"
type Keys = typeof grades[number];
 

Finally, the data type and data can be written as :

type Students = Partial<Record<Keys, string[]>>;
const students: Students = {
Freshman: ["David", "John"],
Junior: ["Lily"],
Senior: ["Tom"],
};
 

In this form , Object's key In fact, there is no grammatical association with the elements in the original array , namely , The editor's 「 Jump definition 」 Is not available .

Screen Shot 2021-05-19 at 3 29 27 PM

Try to keep the relationship between the code to reflect TypeScript The role of , Therefore, it is not recommended to establish an association with only type constraints .

Related resources

The text was updated successfully, but these errors were encountered:

Please bring the original link to reprint ,thank
Similar articles