How to Use the keyof Operator in TypeScript

  1. Use the keyof Operator in TypeScript
  2. Use the keyof Operator With Generics in TypeScript
  3. Use the keyof Operator for Mapped Types in TypeScript
  4. Use the keyof Operator to Extract Keys From Enums With the typeof Operator in TypeScript
  5. Use the keyof Operator to Define Getters in TypeScript
  6. Conclusion
How to Use the keyof Operator in TypeScript

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.

Shuvayan Ghosh Dastidar avatar Shuvayan Ghosh Dastidar avatar

Shuvayan is a professional software developer with an avid interest in all kinds of technology and programming languages. He loves all kinds of problem solving and writing about his experiences.

LinkedIn Website

Related Article - TypeScript Operator