Understanding Object Types in TypeScript: A Comprehensive Guide
Written on
Chapter 1: An Introduction to Object Types
In TypeScript, objects are categorized using object types, which can either be anonymous or named, utilizing either an interface or a type. These object types are essential for organizing and transmitting data to functions. In JavaScript, objects serve as intricate data types comprising key-value pairs. For instance, an object can be defined using the following syntax:
const book = {
publicationDate: Date.now(),
title: "Odysee"
};
In TypeScript, we can explicitly declare the types for the book object:
const typedBook: {
publicationDate: number;
title: string;
} = {
publicationDate: Date.now(),
title: "Odysee"
};
When it comes to passing this object to a function, we can define the object type in two ways: anonymously or using a name.
Anonymous Type Example:
const getBookDate = (book: { publicationDate: number; title: string }): number => {
return book.publicationDate;
};
Named Type Example (using an interface):
interface IBook {
publicationDate: number;
title: string;
}
const getBookDate = (book: IBook): number => {
return book.publicationDate;
};
Named Type Example (using a type):
type Book = {
publicationDate: number;
title: string;
};
const getBookDate = (book: Book): number => {
return book.publicationDate;
};
For instances where an object type is reused frequently, creating a named object type is advisable. If you're uncertain about whether to use a type or an interface, we will delve into their differences in the subsequent section.
When a variable is created without a specified type, TypeScript infers the type as a literal empty object, {}. If an attempt is made to add a property to this empty object, TypeScript will generate an error. For example:
const organization = {};
organization.name = "Sony";
// Error: Property 'name' does not exist on type '{}'.
To resolve this issue, one can utilize the Record utility type or an object index signature. The Record utility type is a built-in TypeScript feature that allows mapping keys to values. Here’s how to implement the Record utility type:
type Organization = Record<string, any>;
const organization: Organization = {};
organization.name = "Sony";
organization.year = 40;
Alternatively, an object index signature can also address this issue. An object index signature defines an object type that permits any property name and type:
interface Organization {
[key: string]: any;
}
const organization: Organization = {};
organization.name = "Sony";
organization.year = 40;
Object vs. Object in TypeScript
In TypeScript, two commonly used object types are object and Object. While they might appear similar at first, they possess significant differences worth noting.
First, consider the object type. This type represents any non-primitive type in TypeScript, which includes arrays, functions, and traditional objects. When a variable is defined as type object, it can be any type that isn't primitive (like string, number, or boolean):
let myObject: object = { name: "John", age: 30 };
In this instance, myObject is an object literal with two properties: name and age. Since it's defined as type object, you cannot access any properties or methods specific to that object. For example, attempting to access the length property (which is specific to arrays) will result in a compile-time error:
console.log(myObject.length);
// Error: Property 'length' does not exist on type 'object'.
Now, let's examine the Object type. This is a built-in class in JavaScript (and hence TypeScript) that provides various methods for working with objects. When a variable is defined as type Object, it signifies that it can be any object, and you can apply the methods offered by the Object class:
let myObject: Object = { name: "John", age: 30 };
console.log(Object.keys(myObject)); // ["name", "age"]
Here, the Object.keys() method is used to retrieve an array of keys in the object. Because myObject is defined as type Object, you can utilize any methods provided by the Object class.
You can also access properties and methods applicable to the Object type. For instance, calling the toString() method on an Object type yields:
let myObject: Object = {
name: "John",
age: 30
};
console.log(myObject.toString()); // [object Object]
It is essential to note that direct access to properties is not possible for objects defined as both object and Object types:
// object type
let myObject: object = {
name: "John",
age: 30
};
console.log(myObject.name);
// Error: Property 'name' does not exist on type 'object'.
// Object type
let yourObject: Object = {
name: "Jane",
age: 25
};
console.log(yourObject.name);
// Error: Property 'name' does not exist on type 'Object'.
Examples of Object Types
Consider the following examples to understand the distinctions better:
let firstObject: object;
firstObject = { prop: 0 }; // OK
firstObject = []; // OK
firstObject = 42; // Error: Type 'number' is not assignable to type 'object'.
firstObject = "string"; // Error: Type 'string' is not assignable to type 'object'.
firstObject = false; // Error: Type 'boolean' is not assignable to type 'object'.
firstObject = null; // Error: Type 'null' is not assignable to type 'object'.
firstObject = undefined; // Error: Type 'undefined' is not assignable to type 'object'.
let secondObject: {}; // or Object
secondObject = { prop: 0 }; // OK
secondObject = []; // OK
secondObject = 42; // OK
secondObject = "string"; // OK
secondObject = false; // OK
secondObject = null; // Error: Type 'null' is not assignable to type '{}'.
secondObject = undefined; // Error: Type 'undefined' is not assignable to type '{}'.
let thirdObject: { [key: string]: any };
thirdObject = { prop: 0 }; // OK
thirdObject = []; // OK
thirdObject = 42; // Error: Type 'number' is not assignable to type '{ [key: string]: any; }'.
thirdObject = "string"; // Error: Type 'string' is not assignable to type '{ [key: string]: any; }'.
thirdObject = false; // Error: Type 'boolean' is not assignable to type '{ [key: string]: any; }'.
thirdObject = null; // Error: Type 'null' is not assignable to type '{ [key: string]: any; }'.
thirdObject = undefined; // Error: Type 'undefined' is not assignable to type '{ [key: string]: any; }'.
let fourthObject: { [key: string]: string };
fourthObject = { prop: "string" }; // OK
fourthObject = { prop: 0 }; // Error: Type 'number' is not assignable to type 'string'.
fourthObject = []; // Error: Type 'never[]' is not assignable to type '{ [key: string]: string; }'.
fourthObject = 42; // Error: Type 'number' is not assignable to type '{ [key: string]: string; }'.
fourthObject = "string"; // Error: Type 'string' is not assignable to type '{ [key: string]: string; }'.
fourthObject = false; // Error: Type 'boolean' is not assignable to type '{ [key: string]: string; }'.
fourthObject = null; // Error: Type 'null' is not assignable to type '{ [key: string]: string; }'.
fourthObject = undefined; // Error: Type 'undefined' is not assignable to type '{ [key: string]: string; }'.
If you have any questions, feel free to ask in the comments.
If you appreciate this content and wish to support me, consider buying me a coffee or clicking the clap button below to show your support. Your encouragement is vital for me to continue creating valuable content — thank you!
Connect with Me
- [LinkedIn](#)
- [Twitter](#)
- [GitHub](#)
Additional Resources
TypeScript Reading List: Reference & Tips And Tricks