TypeScript allows you to define types for variables, function parameters, and return values. This helps catch errors at compile - time rather than runtime. For example:
// Defining a variable with a specific type
let message: string = "Hello, TypeScript!";
// Function with typed parameters and return value
function add(a: number, b: number): number {
return a + b;
}
Interfaces are used to define the structure of an object. They can be used to enforce a certain shape on objects passed to functions or used in other parts of the code.
interface Person {
name: string;
age: number;
}
function greet(person: Person) {
return `Hello, ${person.name}! You are ${person.age} years old.`;
}
Classes in TypeScript are similar to classes in other object - oriented languages. They provide a way to create objects with properties and methods.
class Animal {
constructor(public name: string) {}
speak() {
console.log(`${this.name} makes a sound.`);
}
}
let dog = new Animal("Dog");
dog.speak();
Type annotations are used to explicitly specify the type of a variable or function parameter. They are added after the variable or parameter name, separated by a colon.
let num: number = 10;
function multiply(a: number, b: number): number {
return a * b;
}
TypeScript can often infer the type of a variable based on its initial value. For example:
let greeting = "Welcome"; // TypeScript infers the type as string
Union types allow a variable to have one of several types.
let value: string | number;
value = "Hello";
value = 10;
Organize your code into modules. Use the import
and export
statements to share code between modules.
// math.ts
export function subtract(a: number, b: number): number {
return a - b;
}
// main.ts
import { subtract } from './math';
let result = subtract(5, 3);
Use try - catch blocks to handle errors gracefully. In TypeScript, you can also define custom error types.
class CustomError extends Error {
constructor(message: string) {
super(message);
this.name = "CustomError";
}
}
function divide(a: number, b: number): number {
if (b === 0) {
throw new CustomError("Division by zero is not allowed.");
}
return a / b;
}
try {
let result = divide(10, 0);
} catch (error) {
if (error instanceof CustomError) {
console.log(error.message);
}
}
Type guards are used to narrow down the type within a conditional block.
function printLength(value: string | number) {
if (typeof value === 'string') {
console.log(value.length);
} else {
console.log(value.toString().length);
}
}
Interfaces should have a single responsibility. Avoid creating large, monolithic interfaces.
// Good practice
interface NameInfo {
firstName: string;
lastName: string;
}
interface ContactInfo {
email: string;
phone: string;
}
Enable strict mode in your tsconfig.json
file. This enforces stricter type checking and helps catch more errors.
{
"compilerOptions": {
"strict": true
}
}
Use testing frameworks like Jest or Mocha to write unit tests for your TypeScript code. This helps ensure the correctness of your code and makes it easier to refactor.
// math.test.ts
import { add } from './math';
test('add function should add two numbers correctly', () => {
expect(add(2, 3)).toBe(5);
});
Writing maintainable and scalable TypeScript code is essential for large - scale projects. By understanding the fundamental concepts such as static typing, interfaces, and classes, and following the usage methods, common practices, and best practices outlined in this blog, developers can create high - quality TypeScript applications. Remember to keep your code organized, handle errors gracefully, and use strict mode for better type checking.