How to Use the keyof Operator in TypeScript
-
Use the
keyofOperator in TypeScript -
Use the
keyofOperator With Generics in TypeScript -
Use the
keyofOperator for Mapped Types in TypeScript -
Use the
keyofOperator to Extract Keys From Enums With thetypeofOperator in TypeScript -
Use the
keyofOperator to Define Getters in TypeScript - Conclusion
This tutorial demonstrates how to use the keyof operator in TypeScript.
In TypeScript, there are two types, user-defined and primitive, like number, boolean, and string.
The user-defined types are usually a combination of primitive types in an object. It can be an object representing nested or simple key-value pairs.
Use the keyof Operator in TypeScript
We can use the keyof operator to extract the public property names of a type as a union. It is a vital operator and is widely used in writing generics and reusing existing types.
Example:
interface Person {
name : string;
age : number ;
}
type PersonType = keyof Person;
const AgeAttribute : PersonType = 'age'
const NameAttribute : PersonType = 'name';
The above is a simple example of how we can use the keyof operator to extract the keys from a user-defined type in TypeScript.
The keyof operator returns all the keys of a type as a string union of types. It can also find the keys passed on to the primitive types.
type PrimitiveNumberKeys = keyof number;
// "toString" | "toFixed" | "toExponential" | "toPrecision" | "valueOf" | "toLocaleString"
Although the keyof operator may not be convenient for primitive types, we can still apply it to primitive and user-defined types.
Use the keyof Operator With Generics in TypeScript
TypeScript generics are essential for making widely acceptable function definitions and types.
The keyof operator can add some constraints to the freedom of a function generics. The following code segment explains how we can achieve this.
interface Person {
name : string;
age : number ;
}
function getWitcherAttribute<T, K extends keyof T>( person : T, key : K) : T[K] {
return person[key];
}
const witcher : Person = {
name : 'Geralt',
age : 95
}
console.log(getWitcherAttribute(witcher, 'name'));
Output:
"Geralt"
This keyof operator can be used as a getter for objects of the type defined by the user.
K extends keyof T restricts the keys assigned to K to only keys in the type T. The T[k] returns the same type as in the type T.
Use the keyof Operator for Mapped Types in TypeScript
We have already seen how the keyof operator can use the extends keyword to constrain certain types in generics.
We can further use generics as mapped types using the in keyword.
The following is an implementation of the Partial type in TypeScript.
The Partial type is used for making all fields of a type optional in TypeScript. We implement it using the ? operator, making the keys optional.
interface Person {
name : string;
age : number ;
}
type Optional<T> = {
[K in keyof T]? : T[K]
}
const witcher : Optional<Person> = {
name : "Witcher"
}
Similarly, we can implement the Omit and Pick types in TypeScript.
type PickType<T, K extends keyof T> = {
[P in K] : T[P]
}
type OmitType<T, K extends keyof T> = PickType<T, Exclude<keyof T, K>>
const witcherWithoutAge : OmitType<Person, 'age'> = {
name : "Geralt"
};
const witcherWithOnlyAge : PickType<Person, 'age'> = {
age : 95,
}
The types are defined as PickType and OmitType to avoid duplications with the original Pick and Omit types. These are the actual implementations of the Pick and Omit in TypeScript using the keyof operator.
Use the keyof Operator to Extract Keys From Enums With the typeof Operator in TypeScript
The keyof operator can also extract the keys from an enum.
Example:
enum Colors {
Yellow,
Red,
Black,
Blue,
Green
}
type ColorType = typeof Colors;
type AllColors = keyof ColorType;
// "Yellow" | "Red" | "Black" | "Blue" | "Green"
// it can be also be written together
type AllColors = keyof typeof Colors
This operator is very convenient and can be used to further create the Record type.
Suppose a map is created mapping the colorType to a log message of type string. It can be implemented using the Record type.
Example:
type LogColorMap = Record<AllColors, string>
const LogLevel : LogColorMap = {
Black : "Normal",
Blue : "Info",
Green : "Success",
Red : "Danger",
Yellow : "Warning"
}
Thus, the enum is used to create another type efficiently using the keyof operator.
Use the keyof Operator to Define Getters in TypeScript
We can use the keyof operator to create getters for a type. We use the concept of mapped types and capitalize the keys using the Capitalize type.
Example:
interface Person {
name : string;
age : number ;
}
type Getters<T> = {
[P in keyof T as `get${Capitalize<string & P>}`] : () => T[P];
}
class PersonCls implements Person, Getters<Person> {
age;
name;
constructor(){
this.age = 95;
this.name = "Geralt";
}
getName = () => {
return this.name;
}
getAge = () => {
return this.age;
}
}
const witcher = new PersonCls();
console.log(witcher.getName())
Output:
"Geralt"
Conclusion
Thus, the keyof operator has various use cases and is specially used when creating a library with many generic types. Moreover, it is also used to extract types from existing types and create new ones.
