How keyof keyword is used in TypeScript?


In TypeScript, the keyof keyword plays a significant role when working with objects and their properties. It allows us to obtain the keys of an object and use them to perform various operations. This tutorial will guide you through the usage of keyof, providing syntax explanations and code examples for different scenarios.

Syntax

keyof Type

The above is the syntax for the keyof keyword in TypeScript. The keyof keyword is followed by the name of a type, referred to as "Type." It returns a union type consisting of all the keys (property names) of the specified type. This allows us to access and manipulate an object's keys dynamically.

Example 1: Accessing Object Property Names

The keyof keyword helps us retrieve the names of properties defined within an object type. In this example, we define an interface called "Person" with two properties: "name" of type string and "age" of type number. We then create a type alias "PersonKeys" using keyof to extract the keys from the Person interface. Finally, we assign the value 'name' to a constant named "keys" of type PersonKeys and log its value.

interface Person {
   name: string;
   age: number;
}

type PersonKeys = keyof Person;
const keys: PersonKeys = 'name';
console.log(keys);

On compiling, it will generate the following JavaScript code −

var keys = 'name';
console.log(keys);

Output

The above code will produce the following output −

name

Example 2: Type-Safe Property Access

The keyof keyword enables us to access object properties in a type-safe manner. Here, we define an interface "Car" with properties representing a car's brand, year, and price. We declare a generic function called "getProperty" that takes two arguments: "obj" of type T and "key" of type K, where K extends keyof T. The function returns the value corresponding to the given key in the object. We then create a car object and use the "getProperty" function to retrieve the car's brand property and assign it to the "carBrand" variable. Finally, we log the value of "carBrand”.

interface Car {
   brand: string;
   year: number;
   price: number;
}

function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
   return obj[key];
}

const car: Car = {
   brand: 'Toyota',
   year: 2022,
   price: 25000,
};

const carBrand: string = getProperty(car, 'brand');
console.log(carBrand);

On compiling, it will generate the following JavaScript code −

function getProperty(obj, key) {
   return obj[key];
}
var car = {
   brand: 'Toyota',
   year: 2022,
   price: 25000
};
var carBrand = getProperty(car, 'brand');
console.log(carBrand);

Output

The above code will produce the following output −

Toyota

Example 3: Mapping Object Properties

The keyof keyword is also useful for mapping properties from one object to another. In this example, we define an interface "Fruit" with properties representing the name and color of the fruit. We then create a new type, "FruitMapped" using the keyof within a mapped type. It maps each key in keyof Fruit to the type "string". Finally, we create a "fruit" object using the FruitMapped type and log its value.

interface Fruit {
   name: string;
   color: string;
}

type FruitMapped = {
   [K in keyof Fruit]: string;
};

const fruit: FruitMapped = {
   name: 'Apple',
   color: 'Red',
};

console.log(fruit);

On compiling, it will generate the following JavaScript code −

var fruit = {
   name: 'Apple',
   color: 'Red'
};
console.log(fruit);

Output

The above code will produce the following output −

{ name: 'Apple', color: 'Red' }

Example 4: Conditional Type Mapping

Another powerful application of the keyof keyword is in conditional type mapping. This allows us to selectively map properties based on certain conditions. In this example, we have an interface "Product" representing a product's name, price, and availability. We define a type "DiscountedProducts" that utilizes conditional mapping using keyof. It checks if the property's value extends the "number" type and maps it to the union type of the original value and "null". For all other property types, it keeps the original value type unchanged. Finally, we create a "product" object using the DiscountedProducts type.

interface Product {
   name: string;
   price: number;
   inStock: boolean;
}

type DiscountedProducts<T> = {
   [K in keyof T]: T[K] extends number ? T[K] | null : T[K];
};

const product: DiscountedProducts<Product> = {
   name: 'Widget',
   price: 10,
   inStock: true,
};

console.log(product);

On compiling, it will generate the following JavaScript code −

var product = {
   name: 'Widget',
   price: 10,
   inStock: true
};
console.log(product);

Output

The above code will produce the following output −

{ name: 'Widget', price: 10, inStock: true }

Conclusion

In this tutorial, we have explored the keyof keyword in TypeScript, which enables us to work with object properties more efficiently and safely. We have covered scenarios such as accessing object property names, type-safe property access, mapping object properties, conditional type mapping, and enforcing a subset of object keys. By understanding and utilizing keyof, you can write more robust and maintainable TypeScript code.

The keyof keyword empowers developers to extract, manipulate, and enforce the structure of objects at the type level. It enhances type safety and allows for powerful abstractions. Incorporate keyof into your TypeScript projects to unlock its potential and streamline your development process.

Updated on: 21-Aug-2023

36 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements