When we use TypeScript, we want to use the type system it provides to limit all aspects of the code, the key values of the object, and it is no exception.
For example, we have an object that stores the name of each grade, and the type is roughly like this:
type Students = Record<string, string[]>;
Naturally, the data looks like this:
const students: Students = { Freshman: ["David", "John"], sophomore: [], Junior: ["Lily"], Senior: ["Tom"], };
Restrict object key names to enum
The problem with the above data types is that the grade is limited to several possible values, and attributes can be added to the object at will, which makes the data appear to be not pure enough.
So we add an enum to list the desirable values:
export enum Grade { Freshman, sophomore, Junior, Senior, }
Now, just limit the key names of the object to the enumeration above.
- type Students = Record<string, string[]>; + type Students = Record<Grade, string[]>;
In this way our data can be written like this:
const students: Students = { []: ["David", "John"], []: [], []: ["Lily"], []: ["Tom"], // ❌ Object literal may only specify known properties, and 'blah' does not exist in type 'Students'.ts(2322) blah: ["some one"], };
In this way, the range of key names on the object is limited, and you can see that if you add a key other than an enum, an error will be reported.
More semantic enum values
But there is still something wrong with the above approach, because the enum value is a number starting from 0 by default, so as a key value is not semantic enough, which is reflected when accessing the object's properties:
Fixed our enum to use more semantic text as its value:
export enum Grade { Freshman = "Freshman", sophomore = "sophomore", Junior = "Junior", Senior = "Senior", }
When using this enumeration again, the result is no meaningless number.
If you want, the enum value can also be in Chinese.
export enum Grade { Freshman = "Freshman Newbie", sophomore = "Soul", Junior = "Friends", Senior = "Senior driver", }
There is no problem when using it:
Key value optional
There is another problem with the type definition above, that is, it requires that the object contains all the values in the enum during use, such assophomore
There is no one in this grade, so you can not write it, but you will get an error.
// ❌ Property 'sophomore' is missing in type '{ Freshman: string[]; Junior: string[]; Senior: string[]; }' but required in type 'Students'.ts(2741) const students: Students = { []: ["David", "John"], // []: [], []: ["Lily"], []: ["Tom"], };
Therefore, the optimization type is optional:
type Students = Partial<Record<Grade, string[]>>;
If the optional value is not defined by an enumeration, but comes from an array,
const grades = ["Freshman", "sophomore", "Junior", "Senior"];
This means we need to extract the values in the array to form a union type.
First useconst assertionsTurn the array into tuple type,
const grades = <const>["Freshman", "sophomore", "Junior", "Senior"];
Reusetypeof
andLookup TypesGet the final union type:
// Actually type Keys = "Freshman" | "sophomore" | "Junior" | "Senior"type Keys = typeof grades[number];
The last data type and data can be written as:
type Students = Partial<Record<Keys, string[]>>; const students: Students = { Freshman: ["David", "John"], Junior: ["Lily"], Senior: ["Tom"], };
It should be noted that in this form, the key of the object actually has no syntax correlation with the elements in the original array, that is, the editor's "jump definition" is not available.
Try to maintain the correlation between codes to reflect the role of TypeScript, so operations like this that only type constraints but cannot establish associations are not recommended.
Related resources
const assertions
keyof and Lookup Types
The text was updated successfully, but these errors were encountered:
The above is the detailed content of limiting the range of object key names in TypeScript. For more information about TypeScript restricting the range of object key names, please pay attention to my other related articles!