TYPESCRIPT

TYPESCRIPT Interview Questions and Answers

  1. What is TypeScript?

    • TypeScript is an open-source language developed by Microsoft that builds on JavaScript by adding static type definitions. These types provide a way to describe the shape of objects, providing better documentation and allowing TypeScript to validate your code.

    • It helps catch errors early through a type system and makes JavaScript development more predictable.

  2. How do you compile TypeScript code?

    • TypeScript files (.ts) are compiled into JavaScript using the TypeScript compiler:

      tsc filename.ts
      
    • You can also compile all files in a project with a tsconfig.json using:

      tsc
      
  3. What are the benefits of using TypeScript over JavaScript?

    • Type safety at compile time.

    • Better IDE support with autocompletion and refactoring tools.

    • Interfaces and custom types for cleaner code structure.

    • ESNext features compiled for backward compatibility.

  4. How do you define a variable with a type in TypeScript?

    • Use a colon : after the variable name:

      let age: number = 25;
      const name: string = 'John';
      let isActive: boolean = true;
      
  5. What is type inference in TypeScript?

    • TypeScript automatically infers the type of a variable when it has an initial value.

      let message = "Hello"; // inferred as string
      
    • You don’t need to explicitly declare types unless necessary.

  6. What are the basic types in TypeScript?

    • number, string, boolean, undefined, null, any, unknown, void, never, object

      let id: number = 101;
      let title: string = "TypeScript";
      let isPublished: boolean = true;
      
  7. What is the difference between any and unknown?

    • any: Turns off type checking. Use with caution.

    • unknown: Safer alternative to any. You must perform type-checking before operating on it.

      let valueAny: any = "test";
      let valueUnknown: unknown = "test";
      
      let length1 = valueAny.length; // OK
      // let length2 = valueUnknown.length; // Error
      
      if (typeof valueUnknown === 'string') {
        let length2 = valueUnknown.length; // OK after type narrowing
      }
      
  8. How to create an interface in TypeScript?

    • Interfaces define the structure of an object.

      interface Person {
        name: string;
        age: number;
      }
      
      const user: Person = {
        name: "Alice",
        age: 30
      };
      
  9. What is the difference between interface and type?

    • interface is primarily used for object shapes and supports extension via extends.

    • type is more versatile and can represent unions, intersections, and primitives.

      interface Animal {
        name: string;
      }
      
      type Pet = {
        breed: string;
      };
      
      type Dog = Animal & Pet;
      
  10. How do you define an optional property in an interface?

    • Use ? to mark a property as optional:

      interface Car {
        brand: string;
        color?: string;
      }
      
      const myCar: Car = {
        brand: "Toyota"
      };
      
  11. What is a tuple in TypeScript?

    • A tuple is a fixed-length array with specific types for each element:

      let user: [string, number];
      user = ["Alice", 30];
      
  12. What is an enum and how do you use it?

    • enum allows defining a set of named constants.

      enum Direction {
        Up,
        Down,
        Left,
        Right
      }
      
      let dir: Direction = Direction.Up;
      
  13. How do you make a variable readonly?

    • Use the readonly modifier to make object properties immutable:

      interface Config {
        readonly port: number;
      }
      
      const serverConfig: Config = { port: 8080 };
      // serverConfig.port = 3000; // Error: Cannot assign to 'port'
      
  14. What is the never type in TypeScript?

    • Represents values that never occur. Used for functions that throw or never return:

      function throwError(message: string): never {
        throw new Error(message);
      }
      
  15. What is the void type?

    • Indicates a function returns nothing:

      function logMessage(): void {
        console.log("This is a message");
      }
      
  16. How to use Union types in TypeScript?

    • Union types allow variables to hold more than one type:

      let value: string | number;
      value = "Hello";
      value = 123;
      
  17. What are intersection types?

    • Combine multiple types into one:

      type Admin = {
        name: string;
      };
      
      type Manager = {
        department: string;
      };
      
      type AdminManager = Admin & Manager;
      
  18. What is type assertion in TypeScript?

    • Tells the compiler to treat a value as a specific type:

      let someValue: unknown = "This is a string";
      let strLength: number = (someValue as string).length;
      
  19. What is the difference between == and === in TypeScript?

    • ==: compares values (performs type coercion)

    • ===: compares values and types strictly

      5 == "5" // true
      5 === "5" // false
      
  20. How to define a function with types?

    • Specify parameter and return types:

      function add(a: number, b: number): number {
        return a + b;
      }
      
  21. What are literal types?

    • Allow specifying exact values a variable can hold:

      let direction: "left" | "right" | "up" | "down";
      direction = "left"; // OK
      direction = "north"; // Error
      

Section 2: Intermediate TypeScript Concepts (20+ Questions)

  1. What is a type alias in TypeScript?

    • A type alias allows you to create a new name for a type:

      type Point = {
        x: number;
        y: number;
      };
      
      const pt: Point = { x: 10, y: 20 };
      
  2. What is a union type and where is it useful?

    • Union types allow a variable to hold values of different types:

      let value: string | number;
      value = 'Hello';
      value = 100;
      
    • Useful when a variable may have different types depending on logic.

  3. What are function overloads?

    • Function overloads let you define multiple function signatures:

      function add(a: number, b: number): number;
      function add(a: string, b: string): string;
      function add(a: any, b: any): any {
        return a + b;
      }
      
  4. What is type narrowing?

    • TypeScript uses type guards to narrow a union type to a specific type:

      function print(value: string | number) {
        if (typeof value === 'string') {
          console.log(value.toUpperCase());
        } else {
          console.log(value.toFixed(2));
        }
      }
      
  5. How do you use keyof in TypeScript?

    • It returns a union of keys of a given type:

      interface User {
        id: number;
        name: string;
      }
      
      type UserKeys = keyof User; // 'id' | 'name'
      
  6. What is typeof in a type context?

    • Extracts the type from a variable:

      let user = {
        name: "John",
        age: 30
      };
      
      type User = typeof user;
      
  7. What is a mapped type?

    • Creates a new type by transforming properties of another type:

      type ReadonlyUser<T> = {
        readonly [P in keyof T]: T[P];
      };
      
  8. What is the difference between interface extension and intersection types?

    • Interfaces are extended using extends:

      interface A { a: string; }
      interface B extends A { b: number; }
      
    • Types are merged using &:

      type A = { a: string };
      type B = A & { b: number };
      
  9. What is a discriminated union?

    • A union of types that share a common literal property to help narrow the type:

      type Shape = 
        | { kind: 'circle'; radius: number }
        | { kind: 'square'; side: number };
      
      function area(shape: Shape): number {
        switch (shape.kind) {
          case 'circle': return Math.PI * shape.radius ** 2;
          case 'square': return shape.side * shape.side;
        }
      }
      
  10. What is the in keyword used for in mapped types?

    • Used to iterate over keys in a type:

      type OptionsFlags<T> = {
        [K in keyof T]: boolean;
      };
      
      type Features = OptionsFlags<{ darkMode: () => void; newUserProfile: () => void }>;
      
  11. How does the as keyword help in mapped types?

    • It renames keys during transformation:

      type Events = {
        click: () => void;
        hover: () => void;
      };
      
      type Renamed = {
        [K in keyof Events as `on${Capitalize<K>}`]: Events[K]
      };
      
  12. What is an index signature in TypeScript?

    • Allows specifying properties of a type when the exact names are not known:

      interface StringMap {
        [key: string]: string;
      }
      
  13. How can you make all properties in a type optional?

    • Use the Partial utility type:

      interface Todo {
        title: string;
        completed: boolean;
      }
      
      type PartialTodo = Partial<Todo>;
      
  14. How can you make all properties in a type readonly?

    • Use the Readonly utility type:

      type ReadonlyTodo = Readonly<Todo>;
      
  15. How do you pick specific properties from a type?

    • Use the Pick utility type:

      type TodoTitle = Pick<Todo, 'title'>;
      
  16. How do you omit specific properties from a type?

    • Use the Omit utility type:

      type TodoWithoutCompleted = Omit<Todo, 'completed'>;
      
  17. What is conditional typing in TypeScript?

    • A way to create types based on a condition:

      type IsString<T> = T extends string ? 'yes' : 'no';
      
  18. What is the infer keyword used for?

    • Used in conditional types to infer a type variable:

      type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;
      
  19. How can you extract function parameter types?

    • Use the Parameters utility type:

      function greet(name: string, age: number): void {}
      type GreetParams = Parameters<typeof greet>; // [string, number]
      

Section 3: Advanced Types and Generics (20+ Questions)

  1. What are generics in TypeScript and why are they useful?

    • Generics are a tool that allows components like functions, classes, or interfaces to be reusable for different types rather than working with a single one. This improves code flexibility and type safety.

      function identity<T>(arg: T): T {
        return arg;
      }
      
      const str = identity<string>('hello'); // str is of type string
      const num = identity<number>(123);     // num is of type number
      
  2. How do you constrain generics?

    • You can restrict a generic to certain types or interfaces using extends. This ensures only compatible types can be passed:

      function logLength<T extends { length: number }>(arg: T): void {
        console.log(arg.length);
      }
      
      logLength('hello'); // valid
      logLength([1, 2, 3]); // valid
      // logLength(42); // Error: number doesn't have 'length'
      
  3. What is the default type for a generic?

    • TypeScript allows providing a default value to a generic type parameter when not explicitly passed.

      function wrap<T = string>(value: T): T[] {
        return [value];
      }
      
      const wrapped = wrap(10); // inferred as number[]
      const defaultWrapped = wrap('hello'); // inferred as string[]
      
  4. How do you use multiple type parameters in generics?

    • You can define multiple generics using commas. This is helpful when a function or class relates two or more different types.

      function pair<T, U>(first: T, second: U): [T, U] {
        return [first, second];
      }
      
      const tuple = pair('age', 30); // [string, number]
      
  5. How do you create a generic interface?

    • A generic interface can work with different types dynamically.

      interface Box<T> {
        value: T;
      }
      
      const numberBox: Box<number> = { value: 42 };
      const stringBox: Box<string> = { value: 'TypeScript' };
      
  6. What are conditional types used for?

    • Conditional types define types based on logic:

      type IsString<T> = T extends string ? true : false;
      
      type A = IsString<'abc'>; // true
      type B = IsString<123>;   // false
      
    • They're helpful when transforming types or creating utility types.

  7. How do you extract the return type of a function?

    • Use ReturnType<T> utility to infer the return type of a function:

      function sum(a: number, b: number) {
        return a + b;
      }
      
      type Result = ReturnType<typeof sum>; // number
      
  8. What does infer mean in conditional types?

    • infer lets you capture and reuse a type inside a conditional type:

      type Return<T> = T extends (...args: any[]) => infer R ? R : never;
      
    • Here, R becomes whatever return type the function has.

  9. What is the Extract utility type?

    • Pulls out types that match from a union:

      type T = Extract<'a' | 'b' | 'c', 'a' | 'f'>; // 'a'
      
  10. What is the Exclude utility type?

    • Removes types from a union:

      type T = Exclude<'a' | 'b' | 'c', 'a'>; // 'b' | 'c'
      
  11. What is the NonNullable utility type?

    • Filters out null and undefined:

      type T = NonNullable<string | null | undefined>; // string
      
  12. How do you define recursive types?

    • Recursive types reference themselves. This is often used in tree structures:

      type Tree<T> = {
        value: T;
        children?: Tree<T>[];
      };
      
  13. How do you define a generic constraint using union types?

    • You can restrict a generic to certain primitive types or interfaces:

      function format<T extends string | number>(input: T): string {
        return input.toString();
      }
      
  14. What are utility types in TypeScript?

    • Utility types like Partial, Readonly, Pick, and Omit help transform types:

      interface Todo {
        title: string;
        completed: boolean;
      }
      
      type ReadonlyTodo = Readonly<Todo>; // all props are readonly
      
  15. How do you use Record to define object types?

    • It allows creating an object with known keys and value types:

      type UserRoles = Record<'admin' | 'user', boolean>;
      // Equivalent to:
      // type UserRoles = {
      //   admin: boolean;
      //   user: boolean;
      // };
      
  16. What is a tuple in TypeScript?

    • Tuples represent arrays with fixed length and specific types:

      let tuple: [string, number];
      tuple = ['age', 30]; // OK
      tuple = [30, 'age']; // Error
      
  17. What are labeled tuple elements?

    • Improves readability by naming each element:

      type Point = [x: number, y: number];
      
  18. How can you use generics in classes?

    • You can build reusable class components:

      class GenericBox<T> {
        value: T;
        constructor(value: T) {
          this.value = value;
        }
      }
      
      const box = new GenericBox<number>(123);
      
  19. What are template literal types?

    • Allows building new string literal types from unions:

      type Color = 'red' | 'blue';
      type ButtonVariant = `btn-${Color}`; // 'btn-red' | 'btn-blue'
      
  20. How can you make a deeply readonly type?

    • Recursive mapped types allow deep immutability:

      type DeepReadonly<T> = {
        readonly [P in keyof T]: DeepReadonly<T[P]>;
      };
      
      type Nested = {
        user: {
          name: string;
          address: {
            city: string;
          }
        }
      };
      
      const example: DeepReadonly<Nested> = {
        user: {
          name: 'John',
          address: {
            city: 'Paris'
          }
        }
      };
      
      // example.user.name = 'Jane'; // Error: cannot assign to 'name' because it is a read-only property.
      

Section 4: TypeScript with React, DOM, and Utility Patterns (20+ Questions)

  1. How do you type a React functional component with props in TypeScript?

    • Use React.FC or explicitly type the props:

      interface Props {
        name: string;
      }
      
      const Greeting: React.FC<Props> = ({ name }) => <h1>Hello, {name}!</h1>;
      
  2. Why is it better to avoid React.FC in some cases?

    • It implicitly includes children, which may not be intended, and can make typing defaultProps more complex.

    • Explicitly typing the props is preferred:

      const Greeting = ({ name }: { name: string }) => <h1>Hello, {name}!</h1>;
      
  3. How do you type useState with a specific type?

    const [count, setCount] = useState<number>(0);
    
    • You can also use union types:

    const [status, setStatus] = useState<'loading' | 'success' | 'error'>('loading');
    
  4. How do you type useRef for accessing a DOM element?

    const inputRef = useRef<HTMLInputElement>(null);
    
    useEffect(() => {
      inputRef.current?.focus();
    }, []);
    
  5. How do you type a custom React hook?

    • You define the return and parameter types explicitly:

      function useToggle(initial: boolean): [boolean, () => void] {
        const [state, setState] = useState(initial);
        const toggle = () => setState((s) => !s);
        return [state, toggle];
      }
      
  6. How do you type an event handler in React?

    const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
      console.log(event.target.value);
    };
    
  7. What is the type of setTimeout and setInterval return values in TypeScript (especially in Node vs browser)?

    • In browsers: number, in Node: NodeJS.Timeout. Use ReturnType<typeof setTimeout> for safety.

  8. How do you handle props with optional and default values?

    interface ButtonProps {
      text: string;
      color?: string;
    }
    
    const Button = ({ text, color = 'blue' }: ButtonProps) => (
      <button style={{ backgroundColor: color }}>{text}</button>
    );
    
  9. How do you type a component that accepts children?

    interface Props {
      children: React.ReactNode;
    }
    
    const Wrapper: React.FC<Props> = ({ children }) => <div>{children}</div>;
    
  10. How do you type an event for a button click?

    const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
      console.log('Button clicked');
    };
    
  11. How do you ensure a prop is a union of specific strings?

    type Variant = 'primary' | 'secondary';
    
    interface ButtonProps {
      variant: Variant;
    }
    
  12. How do you type a component with generic props?

    interface ListProps<T> {
      items: T[];
      render: (item: T) => React.ReactNode;
    }
    
    function List<T>({ items, render }: ListProps<T>) {
      return <ul>{items.map(render)}</ul>;
    }
    
  13. What is JSX.Element and when should you use it?

    • JSX.Element is the return type of a React component. Prefer it when defining render functions explicitly.

  14. How do you type asynchronous functions inside React components?

    const fetchData = async (): Promise<void> => {
      const response = await fetch('/api/data');
      const json = await response.json();
      console.log(json);
    };
    
  15. How do you type props for a higher-order component (HOC)?

    • Use generics to retain type safety:

      function withLogging<P>(Component: React.ComponentType<P>) {
        return (props: P) => {
          console.log('Props:', props);
          return <Component {...props} />;
        };
      }
      
  16. How do you type the result of useReducer?

    type State = { count: number };
    type Action = { type: 'increment' | 'decrement' };
    
    const reducer = (state: State, action: Action): State => {
      switch (action.type) {
        case 'increment': return { count: state.count + 1 };
        case 'decrement': return { count: state.count - 1 };
      }
    };
    
    const [state, dispatch] = useReducer(reducer, { count: 0 });
    
  17. How do you type form values in a React form?

    • Define an interface for the form state:

      interface FormState {
        email: string;
        password: string;
      }
      
      const [form, setForm] = useState<FormState>({ email: '', password: '' });
      
  18. What is the type of the event.target.value in a form input?

    • Use React.ChangeEvent<HTMLInputElement> to access event.target.value safely.

  19. How do you handle dynamic keys in form objects with types?

    interface FormFields {
      [key: string]: string;
    }
    
    const [form, setForm] = useState<FormFields>({});
    
  20. How do you use keyof and indexed access types with React props?

    interface Props {
      name: string;
      age: number;
    }
    
    type PropKeys = keyof Props; // 'name' | 'age'
    type NameType = Props['name']; // string
    

Section 5: Type Guards, Type Inference, and Utility Design Patterns (20+ Questions)

  1. What is a type guard in TypeScript?

    • A type guard is a way to narrow down the type of a variable within a conditional block. It helps TypeScript understand more specific types and avoid unsafe operations.

    function isString(value: any): value is string {
      return typeof value === 'string';
    }
    
    function example(value: unknown) {
      if (isString(value)) {
        // TypeScript now knows 'value' is a string here
        console.log(value.toUpperCase());
      }
    }
    
    • Here, isString is a custom type guard that tells TypeScript, "If this function returns true, then value is a string."

  2. How does typeof act as a type guard?

    • The typeof operator is useful to narrow down primitive types:

    function logId(id: string | number) {
      if (typeof id === 'string') {
        console.log(id.toUpperCase());
      } else {
        console.log(id.toFixed(2));
      }
    }
    
    • TypeScript narrows id to string in the first branch and number in the else block.

  3. How does instanceof help in type narrowing?

    • You can use instanceof for class-based type narrowing:

    class Animal {}
    class Dog extends Animal {}
    
    function checkPet(pet: Animal) {
      if (pet instanceof Dog) {
        console.log('It’s a dog');
      }
    }
    
    • Inside the if block, TypeScript understands that pet is of type Dog.

  4. How do you write a custom type guard function?

    interface Admin {
      role: 'admin';
    }
    
    function isAdmin(user: any): user is Admin {
      return user && user.role === 'admin';
    }
    
    • This tells TypeScript that if isAdmin(user) returns true, then user is definitely an Admin.

  5. What is type inference?

    • TypeScript infers the type of a variable when it's obvious from the value:

    let message = 'hello'; // inferred as string
    
    • You don’t need to explicitly annotate types unless necessary.

  6. How can you use in keyword for type narrowing?

    type User = { name: string };
    type Admin = { name: string; accessLevel: number };
    
    function isAdmin(person: User | Admin): person is Admin {
      return 'accessLevel' in person;
    }
    
    • The in operator checks whether a specific property exists on an object.

  7. What are keyof and typeof used for in advanced type manipulations?

    • keyof extracts keys of a type:

    type User = { id: number; name: string };
    type UserKeys = keyof User; // 'id' | 'name'
    
    • typeof gets the type from a declared variable:

    const user = { id: 1, name: 'Jane' };
    type User = typeof user;
    
  8. What is the Record utility type?

    • Creates a type with keys of one type and values of another:

    const userRoles: Record<string, 'admin' | 'user'> = {
      alice: 'admin',
      bob: 'user',
    };
    
    • Here, every key is a string and its value must be either 'admin' or 'user'.

  9. Explain the Partial utility type.

    • Makes all properties in a type optional:

    interface User {
      name: string;
      email: string;
    }
    
    const updateUser = (user: Partial<User>) => {
      // user can have either or both fields, or none
    };
    
  10. What does Required<T> do?

    • Converts all optional properties to required:

    type User = { name?: string };
    type StrictUser = Required<User>; // name is now required
    
  11. What is the Readonly<T> utility?

    • Makes all properties immutable:

    interface Config {
      version: string;
    }
    const config: Readonly<Config> = { version: '1.0' };
    // config.version = '2.0'; // Error: cannot reassign
    
  12. What is Pick<T, K> used for?

    • Selects only specific properties from a type:

    interface User {
      id: number;
      name: string;
      email: string;
    }
    type UserPreview = Pick<User, 'id' | 'name'>;
    
  13. What is Omit<T, K> used for?

    • Removes specific properties from a type:

    type UserWithoutEmail = Omit<User, 'email'>;
    
  14. How does Exclude<T, U> work?

    • Excludes from T those types that are assignable to U:

    type T = Exclude<'a' | 'b' | 'c', 'a'>; // 'b' | 'c'
    
  15. How does Extract<T, U> work?

    • Extracts from T those types that are assignable to U:

    type T = Extract<'a' | 'b' | 'c', 'a' | 'd'>; // 'a'
    
  16. What is NonNullable<T>?

    • Removes null and undefined from a type:

    type T = NonNullable<string | null | undefined>; // string
    
  17. How do you type a function that accepts only one of two fields?

    • You can enforce this with union types and never:

    type OptionA = { a: string; b?: never };
    type OptionB = { a?: never; b: string };
    type Props = OptionA | OptionB;
    
  18. How do you strongly type object keys and values?

    const roles = {
      admin: 'ADMIN',
      user: 'USER',
    } as const;
    
    type RoleKeys = keyof typeof roles; // 'admin' | 'user'
    type RoleValues = (typeof roles)[RoleKeys]; // 'ADMIN' | 'USER'
    
  19. How do you use conditional types?

    • Conditional types work like if statements in the type system:

    type IsString<T> = T extends string ? true : false;
    type Test = IsString<'hello'>; // true
    
  20. How do you infer types within conditional types?
    - Use infer to extract a type from another type:
    ts type ElementType<T> = T extends (infer U)[] ? U : T; type A = ElementType<number[]>; // number

Scroll to Top