Type annotations are a way to explicitly state the type of a variable, function parameter, or return value in TypeScript. They are written after the variable or parameter name, separated by a colon (:
). For example:
let message: string;
message = "Hello, TypeScript!";
In this example, the variable message
is annotated with the string
type. This means that message
can only hold string values. If you try to assign a non - string value to message
, TypeScript will raise a compilation error.
TypeScript has several built - in types, including:
let age: number = 25;
let name: string = "John";
let isStudent: boolean = true;
let emptyValue: null = null;
let unassigned: undefined = undefined;
let numbers: number[] = [1, 2, 3];
let strings: Array<string> = ["a", "b", "c"];
let person: [string, number] = ["John", 25];
let unknownValue: any = "This could be anything";
unknownValue = 10;
As shown in the previous examples, you can annotate variables at the time of declaration.
let price: number = 9.99;
let isAvailable: boolean = false;
If you don’t provide an initial value and a type annotation, TypeScript will infer the type as any
if it cannot determine the type based on the context.
You can annotate the types of function parameters and the return type of a function.
function add(a: number, b: number): number {
return a + b;
}
let result = add(3, 5);
In this example, the add
function takes two parameters of type number
and returns a value of type number
.
If a function doesn’t return a value, you can use the void
type for the return type.
function printMessage(message: string): void {
console.log(message);
}
You can annotate the types of properties in an object literal.
let user: { name: string; age: number } = {
name: "Alice",
age: 30
};
TypeScript can often infer the type of a variable based on its initial value. For example:
let greeting = "Hello"; // TypeScript infers the type as string
It is a good practice to rely on type inference when the type is obvious, as it reduces the amount of boilerplate code.
Union types allow a variable to have one of several types. For example:
let id: number | string;
id = 10;
id = "abc";
This can be useful when a function can accept different types of values.
Type aliases allow you to create a new name for an existing type.
type Point = {
x: number;
y: number;
};
let p: Point = { x: 1, y: 2 };
This makes the code more readable and easier to maintain, especially when dealing with complex types.
Avoid using the any
type unless absolutely necessary. Using specific types helps catch errors early and makes the code more self - documenting.
When defining types, try to keep them close to where they are used. This makes it easier for other developers to understand the code and reduces the chance of introducing bugs when making changes.
Interfaces are similar to type aliases but are mainly used for defining the shape of objects.
interface User {
name: string;
age: number;
}
function printUser(user: User) {
console.log(`${user.name} is ${user.age} years old.`);
}
Interfaces are more extensible than type aliases and are a common choice for defining object types in TypeScript projects.
Type annotations are a core feature of TypeScript that provide many benefits, including early error detection, improved code readability, and better tooling support. By understanding the fundamental concepts, usage methods, common practices, and best practices of type annotations, developers can write more robust and maintainable TypeScript code. Whether you are working on a small project or a large - scale application, leveraging type annotations effectively will enhance your development experience.