Cherreads

Chapter 3 - Typescript

What is TypeScript, and how does it differ from JavaScript?

TypeScript is a superset of JavaScript developed by Microsoft that adds static typing. It compiles down to plain JavaScript, whereas JavaScript is dynamically typed and interpreted directly.

What are the benefits of using TypeScript over JavaScript?

It provides static type checking, early error detection at compile-time, better IDE support (IntelliSense), and improved code maintainability and readability.

Explain the concept of "type annotations" in TypeScript.

Type annotations are a way to explicitly define the type of a variable, function parameter, or return value using a colon syntax (e.g., let name: string).

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

You use the syntax let variableName: type = value;. For example: let age: number = 25;.

What is the any type in TypeScript, and when should it be used?

any disables type checking for a variable, allowing it to hold any value. It should be used sparingly, primarily when migrating legacy code or dealing with dynamic content.

How do you define a function in TypeScript with specific argument and return types?

function add(a: number, b: number): number { return a + b; } specifies that arguments a and b must be numbers, and the function returns a number.

What is type inference in TypeScript?

The compiler's ability to automatically deduce the type of a variable based on the value assigned to it, without needing explicit annotations.

Explain the difference between let, const, and var in TypeScript.

let and const are block-scoped, while var is function-scoped. const creates a read-only reference to a value, while let allows reassignment.

What are TypeScript's primitive types?

The core primitives are string, number, boolean, null, undefined, symbol, and bigint.

What is the difference between undefined and null in TypeScript?

undefined means a variable has been declared but not initialized. null is an assignment value representing an intentional absence of any object value.

How do you define an array in TypeScript?

You can use the type followed by brackets number[] or the generic array type Array.

What is a tuple in TypeScript?

A tuple is an array with a fixed number of elements where the types of elements at specific indices are known and can be different (e.g., [string, number]).

What is an enum in TypeScript, and how is it different from a regular object?

Enums allow defining a set of named constants. Unlike objects, numeric enums offer a reverse mapping (value to name) and are treated as a distinct type.

How do you define an object type in TypeScript?

You define the shape of an object using curly braces, specifying keys and their types: let person: { name: string; age: number };.

What are the differences between TypeScript interfaces and types?

Interfaces are primarily used to define the shape of objects and can be merged. Types are more flexible and can define primitives, unions, tuples, and intersections.

What is the void type in TypeScript?

void represents the absence of a value, commonly used as the return type of functions that do not return a value.

What does never mean in TypeScript, and when is it used?

never represents values that never occur. It is used for functions that always throw an error or have infinite loops.

How does TypeScript handle type compatibility?

TypeScript uses structural typing (duck typing). If two types have the same internal structure (properties and types), they are considered compatible.

What is a type alias, and how does it work in TypeScript?

A type alias creates a new name for a type. It is defined using the type keyword, e.g., type ID = string | number;.

How do you define an optional property in TypeScript?

Add a question mark ? after the property name in an interface or type definition (e.g., name?: string).

What is the purpose of the readonly modifier in TypeScript?

It marks a property as immutable. Once assigned during initialization, the property value cannot be changed.

How do you define a function with optional parameters in TypeScript?

Add a ? to the parameter name in the function signature: function greet(name: string, title?: string). Optional parameters must come last.

How do you define default values for function parameters in TypeScript?

Assign a value in the function signature: function greet(name: string = "Guest"). If no argument is passed, "Guest" is used.

What is the purpose of the as keyword in TypeScript?

It is used for Type Assertions, telling the compiler to treat a value as a specific type (e.g., someValue as string).

How do you use the typeof operator in TypeScript?

It is used to obtain the type of a variable or object at compile time: type Person = typeof personObject;.

What is a namespace in TypeScript, and how is it used?

Namespaces are a way to organize code into logical groups to prevent global scope pollution, though ES Modules are preferred in modern development.

How do you perform type checking in TypeScript?

Type checking is performed by the TypeScript compiler (tsc) during the compilation process, not at runtime.

What is the difference between interface and class in TypeScript?

An interface defines a contract (structure) and disappears at compile time. A class defines implementation and exists in the generated JavaScript.

What are the different ways to import and export modules in TypeScript?

You can use named exports (export const x), default exports (export default x), and import them using ES6 syntax (import { x } from './file').

Explain the concept of "declaration merging" in TypeScript.

When two separate declarations (like two interfaces) share the same name, TypeScript automatically merges them into a single definition.

How do you use the strict mode in TypeScript?

Enable "strict": true in the tsconfig.json file. This turns on a family of strict type checking options (like noImplicitAny, strictNullChecks).

What is the unknown type in TypeScript?

A type-safe counterpart to any. You can assign anything to unknown, but you cannot perform operations on it without narrowing the type first.

What are type guards in TypeScript?

Techniques used to narrow down the type of a variable within a conditional block, such as using typeof, instanceof, or custom predicates.

What are union types, and how are they used in TypeScript?

Union types allow a variable to be one of several types, defined using the pipe | symbol (e.g., string | number).

How do you use the never type in a function that throws an error?

Explicitly set the return type to never: function error(message: string): never { throw new Error(message); }.

What is a "literal type" in TypeScript, and how does it work?

A type that represents a specific value rather than a general category. For example, type Direction = "North" | "South";.

How do you use the keyof keyword in TypeScript?

It produces a string union type of all known, public property names of an object type (e.g., keyof Person might result in "name" | "age").

How do you handle third-party JavaScript libraries in TypeScript?

Install the type definitions via @types/library-name or create a declaration file (.d.ts) if types are not available.

What is the difference between declare and import in TypeScript?

import loads a module for usage. declare is used to define types for variables that exist globally or are loaded externally, without generating code.

How do you enable TypeScript in a JavaScript project?

Install TypeScript (npm install typescript), create a tsconfig.json file, and change file extensions from .js to .ts (or allow JS in config).

Intermediate Level Question

What is the Partial utility type in TypeScript, and how is it used?

It constructs a type with all properties of Type T set to optional. It is useful for update functions where only a subset of properties is needed.

What is the Readonly utility type in TypeScript, and how is it different from readonly properties?

It takes a type T and makes all its properties readonly, whereas the readonly modifier applies to individual properties.

What is the Pick utility type in TypeScript?

It constructs a type by picking a set of properties K (string literal or union) from type T.

How do you use generics in TypeScript to create reusable components?

Generics allow you to define a component/function with a placeholder type (e.g., ) that is specified when the component is used.

What is the extends keyword used for in TypeScript?

It is used for class inheritance (class A extends B) and for constraining generics ().

How do you constrain a generic type in TypeScript?

By using the extends keyword within the angle brackets: function log(arg: T).

What are "mapped types" in TypeScript, and how are they useful?

They allow you to create new types based on old ones by iterating over property keys, often used to make all props optional or readonly.

How does TypeScript handle asynchronous code, and what are Promise and async/await in TypeScript?

TS supports async/await natively. Promise is the return type for async functions, where T is the type of the resolved value.

How do you use the Record utility type in TypeScript?

It creates an object type where keys are of type K and values are of type T. Useful for mapping properties (e.g., Record).

What is the purpose of the this keyword in TypeScript, and how does it differ from JavaScript?

TS allows you to type this in function parameters to explicitly state the context the function expects to be called in, preventing context errors.

What is the difference between interface and abstract class in TypeScript?

An interface only defines the structure. An abstract class can define structure and provide implementation details for some methods.

How do you implement inheritance in TypeScript?

Use the extends keyword for classes to inherit properties and methods from a parent class.

What is the difference between an "interface" and a "type alias" in TypeScript?

Interfaces are generally better for defining object shapes and can be extended. Types are better for defining unions, intersections, and primitives.

What is the significance of the super keyword in TypeScript classes?

It allows a child class to call the constructor or methods of its parent class.

How do you use constructor in TypeScript classes?

The constructor is a special method used to initialize objects. Parameters in the constructor can automatically be mapped to class properties using access modifiers.

What are "mixins" in TypeScript, and how do they work?

Mixins allow building classes from reusable components by combining partial classes. TS implements them via functions that return classes.

How do you declare a read-only property in a class in TypeScript?

Prefix the property name with the readonly keyword inside the class definition or constructor parameter.

How do you create and use custom decorators in TypeScript?

Decorators are functions annotated with @ that wrap classes or members. You must enable experimentalDecorators in tsconfig.

What is the infer keyword in TypeScript, and how does it work?

It is used within conditional types to extract (infer) a type from another type (e.g., inferring the return type of a function).

What is a conditional type in TypeScript?

A type that selects one of two possible types based on a condition, syntax: T extends U ? X : Y.

How does TypeScript support JSX/TSX?

TypeScript supports JSX (React syntax) via the .tsx file extension and the jsx compiler option in tsconfig.json.

How do you perform type assertions in TypeScript?

Use the as keyword (val as string) or angle brackets (val) to tell the compiler to treat a value as a certain type.

What are never and any types, and when should you use them in TypeScript?

any opts out of type checking (use rarely). never indicates a state that shouldn't exist (e.g., exhaustive switch checks).

What is the difference between function and => function syntax in TypeScript?

Regular functions have their own this context. Arrow functions (=>) capture this from the surrounding lexical scope.

How does TypeScript handle module resolution?

It uses strategies (Classic or Node) to locate imported modules, looking at relative paths, node_modules, and tsconfig paths.

How do you use async/await with generics in TypeScript?

You define the function as async and set the return type to Promise: async function fetchData(): Promise.

What is the difference between type and interface when used with generics in TypeScript?

Both support generics. Interfaces syntax is interface Box {}, type syntax is type Box = {}. Functionally very similar.

What is the purpose of the declare keyword in TypeScript?

It asserts that a variable, function, or class exists (usually globally) without providing an implementation, often used for external libs.

How do you use the asserts keyword in TypeScript?

It is used in assertion functions to tell the compiler that if the function returns, a specific condition (type predicate) is true.

What is a "destructuring" assignment in TypeScript, and how does it work?

Unpacking values from arrays or properties from objects into distinct variables, with types inferred or explicitly stated.

How do you define and use interfaces with optional properties in TypeScript?

Define the property with ? (e.g., age?: number). When implementing, you can omit this property.

How do you handle errors and exceptions in TypeScript?

Use try/catch. In the catch block, the error is usually of type unknown or any and must be type-checked before accessing properties.

What are module and namespace in TypeScript, and how do they differ?

module implies external files/ES modules (modern). namespace implies internal organization of code within the global scope (legacy).

How do you perform runtime validation of types in TypeScript?

TypeScript types disappear at runtime. You need to write custom type guard functions or use libraries like Zod or Io-ts.

How do you use the Exclude utility type in TypeScript?

It constructs a type by excluding from UnionType T all union members that are assignable to U.

What is the NonNullable utility type, and when should it be used?

It constructs a type by excluding null and undefined from type T. Useful when you want to ensure a value exists.

How do you avoid common pitfalls in TypeScript type compatibility?

Be aware of structural typing (excess properties might be ignored in some contexts) and avoid overuse of any.

What is the purpose of the void type in TypeScript, and when is it used?

It indicates a function has no return value. Unlike undefined, it explicitly states the return value shouldn't be used.

How do you create a type-safe event system in TypeScript?

Use a mapped type or interface where keys are event names and values are the payload types, ensuring emit/listen args match.

What is the difference between typeof and keyof in TypeScript?

typeof gets the type of a value. keyof gets the union of keys from a type. keyof typeof gets keys of a runtime object.

Experienced Level Question

How do you implement type-safe dependency injection in TypeScript?

Use libraries like InversifyJS or TSyringe that utilize decorators and interfaces to bind implementations to identifiers while preserving types.

What is the significance of never and unknown in TypeScript, and how do you use them effectively?

unknown is for safe input (must check before use). never is for exhaustive checks in switch statements to ensure all cases are handled.

What are advanced patterns of generics, such as "generics with constraints" or "recursive generics" in TypeScript?

Constraints (T extends U) limit types. Recursive generics (e.g., in tree structures) allow a type to reference itself.

How does TypeScript handle and generate declaration files (.d.ts), and why are they important?

The compiler generates .d.ts files when declaration: true is set. They provide type information to consumers without distributing source code.

How would you optimize a TypeScript application in terms of performance and type-checking?

Use Project References (composite projects), incremental builds (--incremental), and avoid expensive recursive types.

What is the role of "type guards" in TypeScript, and how do they enhance type safety?

They enable the compiler to narrow down a broad type (like unknown or a union) to a specific type within a specific scope.

How do you use conditional types for more complex type relationships in TypeScript?

They allow creating types that depend on other types (e.g., ReturnType), enabling highly dynamic type definitions.

How do you implement and enforce "strict null checks" in TypeScript, and why is it important?

Enable strictNullChecks in config. It prevents null/undefined from being assigned to other types, eliminating "cannot read property of undefined" errors.

What is the as const assertion in TypeScript, and how does it help in defining literal types?

It tells the compiler to infer the narrowest possible type (literals) and makes objects/arrays readonly.

How do you handle external JavaScript libraries that don't have type definitions in TypeScript?

Create a global.d.ts file and add declare module 'library-name'; (shorthand) or write a full interface definition.

Explain the concept and use of advanced TypeScript utility types such as ReturnType, Parameters, and InstanceType.

These use conditional types to extract specific parts of a function or class type (e.g., ReturnType gets the result type of a function).

How do you create a type-safe event bus or observer pattern in TypeScript?

Define a mapping interface { EventName: PayloadType } and use generics in the subscribe/emit methods to correlate the name with the payload.

How does TypeScript work with the this context, and what are common pitfalls to avoid?

TS infers this, but it can be lost in callbacks. Use arrow functions or explicitly type the this parameter in the function signature.

What is the significance of "type inference" when using TypeScript generics?

It allows you to call a generic function without specifying the type argument (e.g., func(1) instead of func(1)), making code cleaner.

What is the purpose of the unknown type, and how is it different from any?

unknown forces you to perform a type check before using the value, whereas any allows any operation, making unknown much safer.

How do you design an abstract class in TypeScript that enforces specific contracts while allowing flexibility in implementation?

Use abstract methods for the contract and regular methods/properties for shared logic. Child classes must implement the abstract members.

How do you handle multiple types in a single function signature (overloading) in TypeScript?

Write multiple function signatures (overloads) followed by a single implementation signature that handles all cases loosely.

How would you implement a type-safe configuration management system in TypeScript?

Define a strict configuration interface, use Partial for overrides, and merge default config with user config.

What are the best practices for organizing large TypeScript projects?

Use Monorepos (Nx/Turborepo), Project References, strict path aliases, and separating shared types into their own packages.

What is the infer keyword, and how can it be used in conditional types to infer types?

It declares a type variable within a conditional type to "capture" a type (e.g., getting the element type of an Array).

How do you leverage TypeScript's type system to create reusable, composable components in React or other frameworks?

Use Generic interfaces for Props (interface ListProps), allowing components to handle various data types while maintaining type safety.

What is the role of "module augmentation" in TypeScript, and how would you extend a third-party module's type definitions?

It allows you to add properties to existing interfaces in other modules by declaring a module with the same name and interface.

How does TypeScript's lib.d.ts file work, and how does it impact the development experience?

It contains built-in type definitions for the JS environment (DOM, ES6 methods). Configuring lib in tsconfig controls which environment features are valid.

What is the difference between the typeof operator and the keyof operator in TypeScript, and when would you use each?

typeof converts a value to a type. keyof gets keys of a type. keyof typeof obj is used to get keys of a runtime object as a type.

How do you handle "type erasure" in TypeScript, and how does it affect generics?

Since types are removed at compilation, you cannot check generic types at runtime (e.g., if (arg instanceof T) is invalid).

What is a "recursive type" in TypeScript, and when would you use it?

A type that references itself, used for defining tree structures, linked lists, or JSON data.

What are "mapped types," and how can they be used to transform types in TypeScript?

They iterate over keys of a type to create a new type. Example: type Stringify = { [P in keyof T]: string }.

How does TypeScript work with decorators, and what are some best practices?

Decorators are functions that modify classes/members. Best practice is to keep them pure and side-effect free, mainly for metadata.

How do you handle type-safe API responses using TypeScript?

Define interfaces matching the JSON response. Use generics for a standard wrapper: interface ApiResponse { data: T; status: number }.

What are the trade-offs between using "any" vs. "unknown" in TypeScript for complex applications?

any is faster to write but loses safety. unknown requires more code (checks) but maintains safety. Use unknown whenever possible.

How do you implement and enforce custom validation or transformation logic in TypeScript types?

You can't enforce logic in types alone, but you can use "Branded Types" (intersecting with a unique tag) to ensure values passed validation functions.

What is the importance of the ReadonlyArray type in TypeScript, and how does it differ from a regular array?

It removes all mutating methods (push, pop, splice), ensuring the array contents cannot be changed via that reference.

How do you create a type-safe redux-like state management system in TypeScript?

Use a union of Action types, and use a switch statement in the reducer. TS will infer the specific action type in each case block.

What are the challenges of working with dynamic types or dynamic imports in TypeScript?

The compiler cannot predict the shape of dynamic data. You often have to rely on any or explicit casting after runtime validation.

How do you work with TypeScript's declaration merging to extend existing types or interfaces?

Simply define an interface with the same name as the existing one. TS merges the properties. Useful for adding globals to Window.

How would you design a type-safe API that can return different data types based on input parameters in TypeScript?

Use Function Overloads to define specific return types for specific argument types.

How do you use type inference with generics and conditional types to create dynamic, adaptable components in TypeScript?

By letting TS infer the generic T from props, and using conditional types to decide other prop types based on T.

What is the purpose of as and const assertions in TypeScript, and how do they affect type narrowing?

as manually sets type. as const creates a deeply readonly type and narrows primitives to their literal values.

How do you ensure the scalability and maintainability of a TypeScript codebase in large-scale applications?

Enforce strict mode, use consistent naming, document complex types, modularize code, and automate type checking in CI/CD.

What are some advanced debugging and troubleshooting strategies for TypeScript in a production environment?

Use source maps to debug original TS code in browser/node, and use tsc --noEmit to check for type errors without building.

More Chapters