TypeScript Mid
TypeScript uses a structural type system. Can you explain what that means and how it differs from nominal typing found in languages like Java or C#?
Select the correct answer
Compatibility is checked at runtime by comparing object prototype chains.
Compatibility requires both types to explicitly declare the same exact name.
Compatibility is determined by a type's shape, not by its declared name.
Compatibility requires both types to inherit from a shared base class.
What is Type Inference, and what are the trade-offs between letting TypeScript infer a type versus explicitly annotating it?
Select the correct answer
Inference always produces wider types, while explicit annotations are purely cosmetic.
Inference disables strict checks, while explicit types enable full safety in all cases.
Inference cuts verbosity, while explicit types document intent and guard public APIs.
Inference runs at runtime, while explicit types are validated only during execution.
Explain the concept of 'Erasure' in TypeScript. What happens to your types once the code is compiled and running in the browser?
Select the correct answer
Types are compiled into hidden classes that enforce constraints at runtime.
Types are preserved as metadata accessible through reflection while running.
Types are stripped during compilation and have no presence at runtime.
Types are converted into runtime checks that validate values during execution.
What are the trade-offs of using TypeScript, and when would you not use it?
Select the correct answer
It requires a special runtime, so avoid it when targeting standard web browsers.
It slows runtime performance, so avoid it for any compute-heavy production services.
It blocks modern JS features, so avoid it on projects needing the latest syntax.
It adds build and learning overhead, so skip it for tiny scripts or quick prototypes.
What are 'Utility Types' like Partial, Omit, Pick, and Record? Explain how one of them works under the hood.
Select the correct answer
Omit<T, K> uses a mapped type that strips the readonly modifier from the listed keys.
Partial<T> uses a mapped type that adds the optional modifier to every property of T.
Record<K, T> uses an index-signature loop that copies all values from T into K.
Pick<T, K> uses conditional types to filter out properties not assignable to K.
What is excess property checking and why does it only trigger on object literals?
Select the correct answer
It flags extra properties on object literals assigned directly, since a stored variable could legitimately hold a wider type.
It flags extra properties only on class instances because nominal typing requires their shapes to match exactly.
It flags extra properties on every object because structural typing strictly forbids any unexpected members anywhere.
It flags extra properties on function return values because inference is unable to widen the resulting object type.
What is the difference between the readonly modifier in TypeScript and the const keyword in JavaScript? How does ReadonlyArray differ from a standard array?
Select the correct answer
const deeply freezes objects, while readonly is shallow and ReadonlyArray returns copies of elements.
const works at runtime only, while readonly is identical and ReadonlyArray adds runtime immutability checks.
const blocks rebinding a variable, while readonly blocks property writes and ReadonlyArray hides mutating methods.
const blocks property writes, while readonly blocks rebinding and ReadonlyArray disables index access.
What is an index signature, and what are its limitations compared to a Record type?
Select the correct answer
An index signature types arbitrary keys of one value type, but cannot restrict keys to a finite known set.
An index signature types only a fixed set of keys, but cannot allow values that belong to a union type.
An index signature accepts only numeric keys, but Record additionally permits both string and symbol keys.
An index signature is verified at runtime, but Record performs only compile-time validation of its keys.
Explain the difference between the any and unknown types. Why is unknown considered safer, and how do you eventually use a value typed as unknown?
Select the correct answer
unknown and any are identical at compile time, but unknown is removed from the emitted output.
unknown accepts any value but forbids operations until you narrow it, whereas any disables all checks.
unknown accepts only primitives while any accepts objects, so you must always cast objects before use.
unknown disables checks like any, but additionally emits a runtime warning whenever its value is read.
Explain the never type. When would a function return never, and how is it useful for exhaustive type checking?
Select the correct answer
never represents an empty object; functions returning nothing use it, enabling optional property checks at compile time.
never represents nullable values; functions that might fail return it, enabling stricter non-null assertions in callers.
never represents values that never occur; functions that always throw or loop return it, enabling exhaustiveness.
never represents the void result; functions with no return use it, enabling control-flow narrowing inside branches.
Explain the difference between void and undefined in the context of function return types.
Select the correct answer
void means the return value is ignored, allowing functions that return any value to be assignable there.
void means the function returns undefined exactly, so returning other values raises a type error.
void and undefined are interchangeable, except void cannot be used as a variable type annotation.
undefined means any value is ignored, while void requires an explicit return statement always.
Explain the difference between null and undefined in the context of strictNullChecks.
Select the correct answer
With strictNullChecks, undefined is allowed everywhere while null is banned entirely and must be replaced with optional property values.
With strictNullChecks, both null and undefined stay assignable to any type but the compiler warns whenever they are actually used.
With strictNullChecks, null and undefined merge into one type that is freely assignable to every other type in the program.
With strictNullChecks, null and undefined are separate types not assignable to other types, so each must be handled explicitly.
What are literal types and how do they differ from primitive types?
Select the correct answer
A literal type is any value written directly in source, which the compiler always widens to its primitive type kind.
A literal type is one specific exact value, narrower than the primitive type that includes all values of that kind.
A literal type is a runtime construct holding constants, while primitive types are purely compile-time annotation kinds.
A literal type represents the whole set of strings or numbers, while primitive types restrict variables to one fixed value.
What are .d.ts files? Explain the concept of ambient declarations and when you would need to write a custom declaration file for a third-party library.
Select the correct answer
They hold type declarations without implementation, describing existing code; you write one when a JS library ships no type definitions.
They hold compiled JavaScript output with inline types, describing runtime behavior; you write one to bundle types into a library yourself.
They hold both declarations and implementations for modules, describing logic; you write one to override a library's existing runtime code.
They hold configuration for the compiler's strict options, describing builds; you write one to enable type checking on any untyped imports.
Explain the difference between type-only imports and regular imports. Why is this distinction important for build tools like isolatedModules?
Select the correct answer
import type brings in only runtime values and stays in output, so isolatedModules can strip unused types from every file when bundling.
import type brings in only types and is fully erased in output, so isolatedModules can transpile each file alone without type knowledge.
import type brings in only default exports and is erased later, so isolatedModules can merge declaration files into a single output module.
import type brings in both types and values but defers loading, so isolatedModules can resolve circular dependencies across separate files.
What is the difference between a 'Namespace' and a 'Module' in modern TypeScript, and which one should you use today?
Select the correct answer
Namespaces and modules are identical aliases for the same feature; either one may be used today since the compiler treats both alike.
Namespaces are file-based ES units with import syntax; modules are the older global grouping construct, and namespaces are preferred today.
Namespaces are TypeScript's older way to group code in one global scope; modules are file-based ES modules, which you should use today.
Namespaces compile to separate output files per scope; modules merge everything into one global object, so modules are discouraged today.
What is type narrowing? Explain different ways to achieve it, such as using typeof, instanceof, or custom type predicates with the is keyword.
Select the correct answer
It refines a broad type to a more specific one in a scope via checks such as typeof, instanceof, or is predicates.
It removes all type information during compilation to produce plain JavaScript using guards like instanceof and type predicates.
It widens a specific type to a broader union at runtime via casts such as as, satisfies, or non-null assertions on values.
It converts a value from one type to another permanently using helpers like typeof, keyof, and mapped type transforms.
What is the difference between a type assertion and type casting?
Select the correct answer
A type assertion validates the value at runtime and throws on mismatch, while casting silently ignores any type error at compile time.
A type assertion works only on primitives like numbers and strings, while casting works exclusively on classes and interface instances.
A type assertion only changes the compiler's view with no runtime effect, while casting actually converts the value at runtime.
A type assertion creates a new copy of the object with a new type, while casting mutates the original object's prototype at runtime.
What is the difference between the non-null assertion operator and optional chaining? What are the trade-offs of using the assertion operator?
Select the correct answer
Optional chaining converts nullish values into empty objects at runtime, while the assertion guarantees the property exists at runtime.
Optional chaining works only inside async functions for promises, while the assertion works only on synchronous property access.
Optional chaining throws an error when a value is nullish at runtime, while the assertion provides a default fallback value instead.
Optional chaining returns undefined safely when a value is nullish, while the assertion only silences the compiler's null check.
How do you perform 'Exhaustiveness Checking' in TypeScript to ensure all cases of a union are handled?
Select the correct answer
Use the satisfies operator on the switch statement itself, so the compiler checks that every union member has been listed.
Assign the union value to a never-typed variable in the default case, so any unhandled member triggers a compile error.
Add a runtime assertion in the default case that throws an error, so any unhandled member triggers a thrown exception only.
Enable the strict flag in tsconfig, so the compiler automatically reports any switch statement missing a union member case.
What is the difference between target and lib in your TypeScript configuration?
Select the correct answer
Both control the output version, but target applies to application code and lib applies only to the bundled third-party dependencies
target sets the JavaScript language version of the emitted output; lib chooses which built-in API type declarations are available
target controls the module system of the output while lib determines the directory where compiled declaration files are written out
target chooses which built-in API declarations are available; lib sets the JavaScript language version used for the emitted output files
What are generics in TypeScript? Explain the concept of constraints in generics using the extends keyword and why they are useful for creating reusable components.
Select the correct answer
extends forces a type parameter to inherit from a base class, so only subclasses of that class may be passed to the component
extends merges two type parameters into one intersection, so the component must receive values satisfying both shapes at the same time
extends widens a type parameter to accept any type at all, which removes constraints and lets the component handle every possible input
extends constrains a type parameter to types assignable to a given shape, so the body can safely access the guaranteed properties
What does the keyof operator do, and how is it typically used in conjunction with generics?
Select the correct answer
Produces a union of a type's property values, used as V extends valueof T in generics
Creates a new type by mapping each property of an existing type to an optional one
Produces a union of a type's property names, used as K extends keyof T in generics
Extracts the runtime keys of an object during execution and stores them as an array
How do default type parameters work in generics, and when are they useful?
Select the correct answer
A generic can alias another type like <T as string>, used to rename the parameter
A generic can infer a type from runtime values, used when no value is passed in
A generic can specify a fallback like <T = string>, used when the argument is omitted
A generic can constrain a type like <T extends string>, used to limit the argument
What are Mapped Types, and how do they allow you to create new types based on the properties of an existing type?
Select the correct answer
They merge two existing types using & to build a new combined intersection type
They convert a runtime object using typeof to build a precise literal type from it
They filter a type's keys using extends clauses to build a narrowed subset type
They iterate over a type's keys using [K in keyof T] to build a new transformed type
Explain the keyof operator and the typeof operator. How do they work together to create types based on existing object structures?
Select the correct answer
typeof captures a value's type and keyof its keys, e.g. keyof typeof obj
typeof captures a type's keys and keyof its values, e.g. typeof keyof obj
keyof captures a value's type and typeof its keys, e.g. typeof keyof obj
typeof returns a runtime string and keyof its length, e.g. keyof typeof obj
Explain the satisfies operator introduced in TS 4.9. How does it differ from a standard type assertion or type annotation?
Select the correct answer
It forces a value into a type bypassing checks while keeping its broad declared type
It checks a value conforms to a type while keeping its narrow inferred type
It annotates a value with a type and widens it to match the declared type exactly
It converts a value to a type at runtime while preserving its original literal type
What does the as const assertion do to an object or array? How does it affect type widening?
Select the correct answer
Makes members readonly and narrows literals to exact values, preventing widening
Marks all members optional and infers each as a union with undefined
Freezes the object at runtime so its property values cannot be reassigned later
Widens literal types to their general primitives such as string and number
Explain the difference between the typeof operator in JavaScript versus its use in a TypeScript type context.
Select the correct answer
In JS it returns a runtime string; in a type context it extracts a value's static type
In both contexts it produces a static type used only at compile time for type checks
In both contexts it returns a string describing the runtime category of a value given
In JS it extracts a value's static type; in a type context it returns a runtime string
What are indexed access types (lookup types), like T[K], and how are they used?
Select the correct answer
They constrain K to be a valid key but always return the full original type T
They create a runtime object indexed by K to retrieve property values dynamically
They look up the type of a property by its key, yielding the type stored at that key
They iterate over each key of T to build a mapped type from its property values
Explain the utility types ReturnType, Parameters, and Awaited. How does each extract type information?
Select the correct answer
All three operate on promises, extracting the resolved, rejected, and pending value types
ReturnType gives the return type, Parameters each name, Awaited the async function
ReturnType gives the return type, Parameters the argument tuple, Awaited the resolved value
ReturnType gives the argument tuple, Parameters the return type, Awaited the promise
What is type widening in TypeScript, and how can you prevent it?
Select the correct answer
Narrowing a type inside a type guard; prevent it by using explicit type assertions
Expanding generics to unknown; prevent it by passing explicit type parameters
Inferring a broader type from a literal; prevent with const, as const, or annotations
Expanding union types to include undefined; prevent it with strict null checks
What is a 'Discriminated Union,' and why is it considered a best practice for handling complex state or API responses?
Select the correct answer
A union of types that share all of their fields, distinguished only by their allowed value ranges
A union combined with intersection types in order to merge all of its variants into one shape
A union where each type has fully unique property names so overlap is impossible at runtime
A union of types sharing a common literal tag field that lets TS narrow to the exact variant
What is the difference between a standard enum and a const enum? How does the choice between them affect the compiled JavaScript output?
Select the correct answer
A standard enum emits a runtime object, whereas a const enum is inlined at call sites and emits no object.
Both emit runtime objects, but a const enum additionally freezes its members to prevent later reassignment.
Neither emits runtime code, but a standard enum allows reverse mapping while a const enum forbids it.
A standard enum is inlined at usage sites, whereas a const enum emits a lookup object preserved at runtime.
Explain the difference between private, protected, and the native JavaScript #private fields.
Select the correct answer
All three are enforced at runtime, differing only in whether the member name is mangled in the output.
private and protected are erased compile-time checks, while #private fields are truly private at runtime.
All three are erased at compile time, differing only in whether subclasses may access the member directly.
private and protected are enforced at runtime, while #private fields exist only as compile-time annotations.
What is an abstract class and how does it differ from an interface?
Select the correct answer
Both exist at runtime, but an abstract class cannot be instantiated whereas an interface freely can be.
An abstract class can hold implementation and exists at runtime, while an interface is erased and type-only.
Both are erased at compile time, but an abstract class may declare constructors while an interface may not.
An interface can hold implementation and exists at runtime, while an abstract class is erased and type-only.
How does function overloading work in TypeScript compared to languages like Java or C#?
Select the correct answer
You declare each signature in a separate interface, and the compiler merges them into methods like C#.
You declare multiple signatures over one implementation; there are no separate bodies, unlike Java or C#.
You annotate one signature with overload decorators, and the runtime selects the body as Java or C# does.
You write multiple implementation bodies, and the compiler emits runtime dispatch much like Java or C#.
What are the trade-offs of using enum versus a const object or a union of string literals? Why do some teams ban the use of Enums entirely?
Select the correct answer
Enums lack exhaustiveness checks that unions provide, so banning them removes a redundant safety guarantee.
Enums are fully type-checked but string unions always need extra explicit runtime validation to work safely.
Enums emit extra runtime JavaScript, while string unions and const objects are erased, so teams avoid them.
Enums cannot hold string values at all, which forces teams to migrate toward const objects instead.
When typing React components, what is the difference between React.ReactNode and React.ReactElement?
Select the correct answer
ReactNode is anything renderable like strings, numbers, or null; ReactElement is a single element object.
ReactNode and ReactElement are identical aliases whose difference is purely stylistic in modern typings.
ReactNode represents browser DOM nodes, while ReactElement represents virtual component instances at runtime.
ReactElement accepts strings, numbers, and arrays, while ReactNode only accepts a single JSX element object.
Why is it generally discouraged to use React.FC (FunctionComponent) in modern React-TypeScript projects?
Select the correct answer
It prevents components from using hooks, forcing them back into class components for any stateful logic.
It breaks server-side rendering by attaching runtime metadata that cannot be serialized into plain HTML.
It implicitly added a children prop and complicates generic components, offering little real benefit.
It disables prop type inference entirely, requiring every prop to be cast manually at each call site.