Table of Contents
Working with Dynamic Object Keys
Working with dynamic object keys in TypeScript allows developers to create more flexible and dynamic code. Instead of relying on static keys, which are predefined and cannot be changed at runtime, dynamic keys can be generated or modified dynamically based on certain conditions or user input.
In TypeScript, dynamic object keys can be useful in scenarios such as:
- Working with JSON data that has variable keys.
- Creating dynamic data structures.
- Accessing object properties dynamically.
- Validating and checking the type of object keys.
In this tutorial, we will explore various techniques and examples of working with dynamic object keys in TypeScript.
Related Article: How to Convert a String to a Number in TypeScript
Creating an Object with a Dynamic Key
To create an object with a dynamic key in TypeScript, you can use the bracket notation. This allows you to specify the key as a variable or an expression. Here's an example:
const dynamicKey = 'age';
const person = {
name: 'John',
[dynamicKey]: 25,
};
console.log(person); // { name: 'John', age: 25 }
In this example, we define a variable dynamicKey with the value 'age'. We then create an object person using the bracket notation to assign the value 25 to the age key. The resulting object will have the properties name and age.
Accessing Object's Property using Dynamic Key
To access an object's property using a dynamic key in TypeScript, you can also use the bracket notation. Here's an example:
const dynamicKey = 'age';
const person = {
name: 'John',
age: 25,
};
console.log(person[dynamicKey]); // 25
In this example, we define a variable dynamicKey with the value 'age'. We then access the age property of the person object using the bracket notation with the dynamicKey variable. The result will be 25.
Defining the Type of an Object Key
In TypeScript, you can define the type of an object key using the keyof keyword. This allows you to specify that a variable should be of a certain key of an object. Here's an example:
const person = {
name: 'John',
age: 25,
};
type PersonKey = keyof typeof person;
let key: PersonKey;
key = 'name'; // Valid
key = 'age'; // Valid
key = 'address'; // Error: Type '"address"' is not assignable to type 'PersonKey'
In this example, we define an object person with properties name and age. We then define a type PersonKey using the keyof keyword and the typeof operator to get the keys of the person object. We declare a variable key with the type PersonKey and assign different keys to it. TypeScript will enforce that the assigned values must be valid keys of the person object.
Related Article: How to Run Typescript Ts-Node in Databases
Inferring the Type of an Object Key
In TypeScript, the type of an object key can be inferred based on its usage. This allows you to write more concise code without explicitly specifying the type. Here's an example:
const person = {
name: 'John',
age: 25,
};
const key = 'name';
const value = person[key];
console.log(typeof value); // string
In this example, we have an object person with properties name and age. We define a variable key with the value 'name'. When we access the person object using the key variable, TypeScript infers that the type of the value variable is string, as the name property is of type string.
Checking the Type of an Object Key
To check the type of an object key in TypeScript, you can use the in operator. This allows you to determine whether a certain key exists in an object. Here's an example:
const person = {
name: 'John',
age: 25,
};
const key = 'name';
if (key in person) {
console.log('Key exists in the person object');
} else {
console.log('Key does not exist in the person object');
}
In this example, we have an object person with properties name and age. We define a variable key with the value 'name'. By using the in operator, we can check if the key exists in the person object. If it does, the code inside the if block will be executed; otherwise, the code inside the else block will be executed.
Validating Object Keys
In TypeScript, you can validate object keys using type guards and conditional statements. This allows you to ensure that only valid keys are used when accessing object properties dynamically. Here's an example:
const person = {
name: 'John',
age: 25,
};
function validateKey(key: string): key is keyof typeof person {
return key in person;
}
function getProperty(key: string) {
if (validateKey(key)) {
return person[key];
} else {
throw new Error('Invalid key');
}
}
console.log(getProperty('name')); // John
console.log(getProperty('address')); // Error: Invalid key
In this example, we have an object person with properties name and age. We define a function validateKey that takes a key parameter and checks if it exists in the person object. The key is keyof typeof person type guard is used to narrow down the type of the key parameter. We then define a function getProperty that takes a key parameter and uses the validateKey function to validate the key before accessing the person object. If the key is valid, the corresponding property value is returned; otherwise, an error is thrown.
Dynamic Keys in TypeScript and JavaScript
Dynamic keys are not specific to TypeScript and can also be used in JavaScript. However, TypeScript provides additional type checking and type inference capabilities, which can help catch potential errors and provide better developer experience.
In JavaScript, you can use the same techniques mentioned earlier to work with dynamic object keys. Here's an example:
const person = {
name: 'John',
age: 25,
};
const dynamicKey = 'age';
console.log(person[dynamicKey]); // 25
In this example, we have an object person with properties name and age. We define a variable dynamicKey with the value 'age'. By using the bracket notation, we can access the age property of the person object dynamically.
Related Article: Tutorial: Converting Boolean to String in TypeScript
Handling Non-Existent Keys in TypeScript
When working with dynamic object keys in TypeScript, it's important to handle cases where the key does not exist in the object. Otherwise, the code may throw a runtime error. One way to handle this is by using optional chaining and nullish coalescing operators.
Optional chaining (?.) allows you to safely access nested properties without throwing an error if a property along the chain is null or undefined. Nullish coalescing (??) allows you to provide a default value if the accessed property is null or undefined. Here's an example:
const person = {
name: 'John',
age: 25,
};
const key = 'address';
const address = person?.[key] ?? 'Unknown';
console.log(address); // Unknown
In this example, we have an object person with properties name and age. We define a variable key with the value 'address'. By using optional chaining (?.) and nullish coalescing (??), we can safely access the address property of the person object. If the address property is null or undefined, the default value 'Unknown' will be used instead.
Changing the Type of an Object Key
In TypeScript, it's possible to change the type of an object key by using mapped types. Mapped types allow you to transform the keys of an object type into a different type. Here's an example:
type Person = {
name: string;
age: number;
};
type KeyToUpperCase = {
[K in keyof T as Uppercase]: T[K];
};
const person: KeyToUpperCase = {
NAME: 'John',
AGE: 25,
};
console.log(person); // { NAME: 'John', AGE: 25 }
In this example, we have a type Person with properties name and age. We define a mapped type KeyToUpperCase that transforms the keys of the Person type to uppercase using the Uppercase utility type. We then declare a variable person with the KeyToUpperCase type and assign values to the transformed keys (NAME and AGE).
Case-Sensitivity of Object Keys in TypeScript
In TypeScript, object keys are case-sensitive. This means that name and Name are considered as different keys. Here's an example:
const person = {
name: 'John',
};
console.log(person.name); // John
console.log(person.Name); // undefined
In this example, we have an object person with a property name. When we access the name property using the correct case (person.name), we get the value 'John'. However, when we use a different case (person.Name), we get undefined because it is treated as a different key.
External Sources
- TypeScript Documentation: Indexable Types