TypeScript Language Features

Basic Types and Type Annotations

One of the core features of TypeScript is support for type annotations, allowing developers to explicitly declare types before variables, function parameters, or return values. This enhances code readability and safety. For example:

let name: string = "Alice";  
let age: number = 25;  

Type annotations help static type checking tools (such as the TypeScript compiler) identify potential errors like mismatched assignment types.

Type Inference and Dynamic Types

TypeScript automatically infers variable types through type inference, eliminating the need for explicit declarations. For example:

let x = 10; // Infers type as number  
let y = "hello"; // Infers type as string  

This mechanism is particularly common in function parameters, allowing developers to omit type declarations and keep code concise.

Optional Properties and Defaults

TypeScript supports optional properties, enabling certain attributes within an object definition to be marked as optional. For example:

interface User {  
  name: string;  
  age?: number; // Optional property  
}  

Developers can provide default values for optional properties using the default attribute, enhancing code flexibility.

Interfaces and Classes

Interfaces are used to define the shape of objects, while classes implement these interfaces. For example:

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

class Person implements User {  
  name: string;  
  age: number;  
}  

Interfaces constrain object properties and methods, whereas classes provide the structure for object-oriented programming.

Enums and Type Aliases

Enums allow developers to define a set of named constants. For example:

enum Color { Red, Green, Blue }  

Type aliases (Type Aliases) can create custom types, improving code maintainability:

type Animal = "dog" | "cat";  

These features make TypeScript's type system more flexible and support complex type combinations.

Generic Types and Generics

Generics allow parameters to be used when defining types, enabling flexible type operations. For example:

function createArray<T>(arr: T[]): T[] {  
  return [...arr]; // Return a new array with the same elements
}  

Generics can be applied to arrays, functions, classes, etc., ensuring both type safety and code reusability.

Static Type Checking and Runtime Checks

TypeScript's static type checking detects type errors during compilation, avoiding runtime crashes. For example:

function add(a: number, b: number): number {  
  return a + b; // Returns the sum of two numbers
}  

This feature makes code more reliable, especially in large projects or scenarios requiring strict type constraints.

Type Assertions and Type Guards

Developers can temporarily specify types using type assertions or determine types at runtime with type guards. For example:

let x: any = "hello";  
let y: string = x as string; // Type assertion

Type guards (such as x instanceof String) further refine type-checking logic.

Code Maintainability and Type Safety

The features of TypeScript collectively enhance code maintainability by reducing runtime errors through mechanisms like type annotations, interfaces, and generics, thereby improving development efficiency.