TYPESCRIPT
TypeScript Annotations: Syntax, Usage, and Examples
TypeScript annotations let you define the types of variables, function parameters, return values, and objects in your code. They help you catch errors early and make your code easier to read and maintain.
What Are TypeScript Annotations?
TypeScript annotations specify data types in your code, ensuring values match their expected types. These annotations do not affect the compiled JavaScript but help you write more reliable code.
let message: string = "Hello, TypeScript!";
let count: number = 10;
Here, message
must always hold a string, and count
must always be a number.
Type Annotations Can Only Be Used in TypeScript
Type annotations exist only in TypeScript. JavaScript does not support them, so when you compile your TypeScript code, the TypeScript compiler removes them.
How to Use TypeScript Annotations
Use Type Annotations with Variables
You can define types for different values:
let isDone: boolean = false;
let amount: number = 42;
let userName: string = "Alice";
let hobbies: string[] = ["Reading", "Gaming"];
Add Type Annotations to Functions
Type annotations help prevent incorrect arguments and return values.
function add(a: number, b: number): number {
return a + b;
}
function greet(name: string): string {
return `Hello, ${name}!`;
}
If you try passing a string to add()
, TypeScript will throw an error.
Define Object Type Annotations
Use type annotations to describe objects:
type User = {
name: string;
age: number;
isActive: boolean;
};
let user: User = {
name: "John",
age: 30,
isActive: true,
};
This ensures that every User
object has the correct structure.
When Should You Use TypeScript Annotations?
Prevent Errors Before They Happen
Type annotations stop you from assigning incorrect values:
let total: number;
total = "100"; // Error: Type 'string' is not assignable to type 'number'.
Make Your Code Easier to Read
Annotations clarify what data your functions expect and return.
function multiply(a: number, b: number): number {
return a * b;
}
Anyone reading this function knows it takes two numbers and returns a number.
Create Custom Types
Define reusable types to keep your code consistent:
interface Product {
id: number;
name: string;
price: number;
}
let item: Product = { id: 1, name: "Laptop", price: 999.99 };
If you try adding a category
field, TypeScript will warn you.
Examples of TypeScript Annotations
Use Type Annotations with Arrays
let numbers: number[] = [1, 2, 3, 4, 5];
let users: string[] = ["Alice", "Bob", "Charlie"];
Use Optional and Default Parameters
You can make function parameters optional or set default values:
function getFullName(firstName: string, lastName?: string): string {
return lastName ? `${firstName} ${lastName}` : firstName;
}
console.log(getFullName("Alice")); // Alice
console.log(getFullName("Alice", "Smith")); // Alice Smith
Use Generics to Keep Types Flexible
Generics let you use annotations while allowing different types:
function identity<T>(arg: T): T {
return arg;
}
console.log(identity<string>("Hello")); // Hello
console.log(identity<number>(42)); // 42
Specify Function Return Types
Explicit return types help avoid unintended results:
function getDiscount(price: number): number {
return price * 0.1;
}
Type Annotations vs. Decorators
Type annotations define variable and function types at compile time, while decorators modify runtime behavior.
function Log(target: any, propertyKey: string) {
console.log(`${propertyKey} was accessed`);
}
class Example {
@Log
message: string = "Hello";
}
Use type annotations to enforce correctness and decorators to add metadata or change behavior dynamically.
TypeScript Custom Annotations
You can create custom types for structured data.
type ApiResponse<T> = {
status: number;
data: T;
};
let response: ApiResponse<string> = { status: 200, data: "Success" };
Use the TypeScript Override Annotation
The override
keyword ensures child classes correctly override methods from parent classes.
class Base {
greet(): string {
return "Hello from Base";
}
}
class Derived extends Base {
override greet(): string {
return "Hello from Derived";
}
}
If greet()
does not exist in Base
, TypeScript will show an error.
Use the TypeScript Deprecated Annotation
Mark functions as deprecated using JSDoc comments.
class Legacy {
/**
* @deprecated Use newMethod() instead.
*/
oldMethod() {
console.log("Deprecated method");
}
newMethod() {
console.log("New method");
}
}
This warns developers to avoid using outdated methods.
TypeScript Variance Annotations
Variance annotations control how types relate in generics. TypeScript supports covariance (subtypes allowed) and contravariance (supertypes allowed).
Covariance Example
class Animal {}
class Dog extends Animal {}
let animals: Animal[] = [new Dog()]; // Allowed
Contravariance Example
type Callback = (arg: Dog) => void;
let handler: Callback = (animal: Animal) => {}; // Allowed
Covariance lets you assign a subtype where a supertype is expected. Contravariance works in reverse.
Learn More About TypeScript Annotations
Let TypeScript Infer Types for Simplicity
TypeScript guesses types if you do not specify them.
let age = 25; // Inferred as number
For clarity, use explicit annotations when needed:
let score: number = 100;
Use Union and Intersection Types
Union types allow multiple types:
let value: string | number;
value = "Hello"; // Valid
value = 42; // Valid
Intersection types merge multiple types:
type Developer = { name: string };
type Engineer = { skills: string[] };
type DevOps = Developer & Engineer;
let employee: DevOps = { name: "Alice", skills: ["Docker", "AWS"] };
Use Enums and Literal Types
Enums create named constants:
enum Status {
Active,
Inactive,
Pending,
}
let currentStatus: Status = Status.Active;
Literal types restrict values:
let theme: "light" | "dark";
theme = "light"; // Valid
theme = "blue"; // Error
Sign up or download Mimo from the App Store or Google Play to enhance your programming skills and prepare for a career in tech.