Basic

6. How do you ensure type safety in your TypeScript code and prevent runtime errors?

Overview

Ensuring type safety in TypeScript code is crucial for preventing runtime errors. TypeScript, being a statically typed superset of JavaScript, provides powerful tools for type checking at compile time, thus reducing the possibility of type-related bugs in runtime. Understanding how to leverage TypeScript's type system effectively is vital for developing robust applications.

Key Concepts

  1. Type Annotations: Declaring variable types to enforce type checking.
  2. Interfaces and Types: Defining custom types for objects and function signatures to ensure structural compatibility.
  3. Generics: Allowing components to work with any type rather than a single one, improving code reusability and type safety.

Common Interview Questions

Basic Level

  1. How do you declare a variable with a specific type in TypeScript?
  2. What is the purpose of interfaces in TypeScript?

Intermediate Level

  1. How do generics enhance type safety in TypeScript?

Advanced Level

  1. Can you explain how to use conditional types in TypeScript for type inference optimization?

Detailed Answers

1. How do you declare a variable with a specific type in TypeScript?

Answer: In TypeScript, you declare a variable with a specific type by using a colon (:) followed by the type after the variable name. This enforces the variable to hold only values of the specified type, ensuring type safety.

Key Points:
- Type annotations help catch errors at compile time.
- Basic types include: string, number, boolean, null, undefined, symbol, and any.
- Using any type defeats the purpose of type checking and should be avoided when possible.

Example:

let message: string = "Hello, TypeScript";
let age: number = 30;
let isStudent: boolean = false;

// Trying to assign a different type will result in a compilation error
message = 42; // Error: Type 'number' is not assignable to type 'string'.

2. What is the purpose of interfaces in TypeScript?

Answer: Interfaces in TypeScript define the shape of an object, specifying the expected properties along with their types. This helps to ensure objects match a specific structure, enhancing type safety and code predictability.

Key Points:
- Interfaces are used for type-checking properties and their types in objects.
- They can be extended or implemented, promoting code reusability.
- Interfaces can also define function types, specifying the parameters and return type of functions.

Example:

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

function greet(person: Person) {
    console.log(`Hello, ${person.name}`);
}

greet({ name: "Alice", age: 30 }); // Correct usage
greet({ name: "Bob" }); // Error: Property 'age' is missing in type '{ name: string; }'

3. How do generics enhance type safety in TypeScript?

Answer: Generics in TypeScript allow functions, classes, and interfaces to work with any data type without losing the information about that type. This makes it possible to create reusable and flexible components while maintaining type safety.

Key Points:
- Generics provide a way to use types as variables in other types, making components adaptable.
- They help in maintaining type integrity throughout the operation, reducing runtime errors.
- Generics can be constrained to ensure they work with a certain set of types.

Example:

function getArray<T>(items : T[]) : T[] {
    return new Array<T>().concat(items);
}

let numberArray = getArray<number>([5, 10, 15, 20]);
let stringArray = getArray<string>(["Alice", "Bob", "Charlie"]);

// numberArray.push("String"); // Error: Argument of type 'string' is not assignable to parameter of type 'number'.

4. Can you explain how to use conditional types in TypeScript for type inference optimization?

Answer: Conditional types in TypeScript allow the type system to choose between types based on conditions. They are a powerful feature for enhancing type inference and optimization by making types depend on other types, akin to ternary operations but for types.

Key Points:
- Conditional types follow the format T extends U ? X : Y, where T is checked against U to decide between X and Y.
- Useful in generic programming where the type might change based on input types.
- They help in creating type-safe utilities that can adapt based on input.

Example:

type IsString<T> = T extends string ? "Yes" : "No";

type Result1 = IsString<string>; // "Yes"
type Result2 = IsString<number>; // "No"

// This can be used to create conditional behaviors in functions and classes based on the resolved type.

This guide covers the basics of ensuring type safety in TypeScript and should serve as a foundation for further exploration of TypeScript's type system.