Top 30 Generics Interview Questions and Answers
30 multiple-choice questions on Generics, drawn from 30 bites out of the 50 tagged Generics on Tezvyn. Answer them here or read straight down. Every question carries the correct option, why it is correct, and a link to the bite it came from.
30 questions. Pick an answer, or open “Show the answer” to read it.
Answers are graded in your browser. Nothing is saved, and no XP or streak is earned here. The app keeps score.
Question 1 of 30
Which getProperty signature both rejects invalid keys at compile time and returns the exact type of the requested property?
Show the answer
Answer: c · Two generics T and K where K extends keyof T and the return type is T[K]
Option C is correct because constraining K with extends keyof T limits keys to valid properties on T, while T[K] preserves the exact type of the accessed property. Option D is tempting because keyof T does restrict keys, but T[keyof T] produces a union of all property types rather than the specific one for the key passed.
Read the full bite: Create a generic getProperty using generics and keyof
Question 2 of 30
What is the primary benefit of defining a Rust trait, such as Summary with a summarize method, and implementing it for multiple distinct types?
Show the answer
Answer: b · It allows writing generic functions that can operate on any type that fulfills the Summary contract, promoting code reuse.
The card states traits enable "writing generic functions that can accept any type that fulfills a certain contract," which directly leads to code reuse and abstraction. Option D is a tempting distractor because traits can have default implementations, but the primary benefit isn't the automatic provision of a default, but rather the ability to treat different types uniformly based on their shared behavior.
Question 3 of 30
When writing a swap function in Swift, what advantage does using a generic placeholder T provide over accepting parameters of type Any?
Show the answer
Answer: d · Generics enforce that both parameters are the same concrete type and avoid runtime casting
Generics preserve compile-time type information, ensuring both arguments share the same type and eliminating unsafe downcasting. Distractor A is tempting because Any permits heterogeneous values, but a generic swap<T> explicitly prevents mixing types, which is exactly why it is type-safe.
Read the full bite: What are Swift generics, why useful, and write a swap function?
Question 4 of 30
What primary problem do Dart generics address in software development?
Show the answer
Answer: b · Allowing code to operate on different data types without sacrificing compile-time type safety.
Generics solve the problem of writing code that works with various data types while maintaining type safety at compile time, preventing errors that would arise from using less specific types like Object or dynamic. Option A is incorrect because generics enforce type safety at compile-time, which is distinct from dynamic typing that defers type checking to runtime.
Read the full bite: Dart Generics: Type-Safe Containers and Reusable Code
Question 5 of 30
What is the primary reason to use an associated type within a Swift protocol?
Show the answer
Answer: b · To enable the protocol to refer to a type whose concrete definition is only known by conforming types.
Associated types exist to allow a protocol's blueprint to refer to a type that is not known until a concrete type adopts the protocol, making the protocol generic over types it uses. Option C is a tempting distractor because, while desirable, the card explicitly states that protocols with associated types cannot be used directly as concrete types for variables or collections without workarounds.
Read the full bite: Associated Types: Making Protocols Generic
Question 6 of 30
What is the primary implication of declaring a generic type parameter with the `out` modifier, as in `interface Source<out T>`?
Show the answer
Answer: b · It allows an instance of `Source<String>` to be used where `Source<Any>` is expected.
The `out` modifier indicates covariance (a producer), which preserves the subtyping relationship. This allows a `Source<subtype>` (like `String`) to be used as a `Source<supertype>` (like `Any`). A common misconception is that `out` implies immutability, but it only enforces type safety.
Read the full bite: Explain Kotlin's declaration-site variance with `in` and `out`
Question 7 of 30
What is the primary type-system benefit of declaring an interface as Producer<out T> when T only appears in return positions?
Show the answer
Answer: b · It lets Producer<String> be used where Producer<Any> is expected without caller-side wildcards.
Marking T with out makes Producer covariant, so Producer<String> is a subtype of Producer<Any> and callers never need wildcards. Option C is wrong because variance does not imply immutability; the class may still mutate state via operations that do not mention T.
Read the full bite: Explain Kotlin's declaration-site variance with in and out
Question 8 of 30
To maximize type flexibility for a generic interface DataSink<T> that exclusively consumes elements of type T, which variance modifier should be used?
Show the answer
Answer: b · in T
The 'in' modifier is used for contravariant types that act as consumers, allowing a supertype (e.g., DataSink<Any>) to be used where a subtype (e.g., DataSink<String>) is expected, thus maximizing flexibility. The 'out' modifier is for producers, which would be incorrect for a consumer interface.
Read the full bite: Explain Kotlin's declaration-site variance with in and out
Question 9 of 30
What is the fundamental reason Kotlin's `reified` type parameters must be used with `inline` functions?
Show the answer
Answer: b · The inline mechanism enables the compiler to replace the generic type parameter with the actual type at the call site before JVM type erasure occurs.
Correct answer (B) states that `inline` allows the compiler to substitute the generic type with its concrete type at the call site, effectively baking the type information into the bytecode before JVM type erasure. Option C is incorrect because `reified` does not bypass JVM type erasure; instead, the compiler works around it by substituting the type during inlining.
Read the full bite: Explain Kotlin's `reified` type parameters and their use case
Question 10 of 30
Why can a reified type parameter be checked with is T at runtime despite JVM type erasure?
Show the answer
Answer: c · The compiler substitutes the concrete type into the inlined body at each call site.
Inline expansion lets the compiler replace T with the concrete type at the call site, emitting a real instanceof check. Option A is tempting but wrong because reified does not rely on reflection or pass a Class object; it works by bytecode substitution during compilation.
Read the full bite: What is a reified type parameter in Kotlin?
Question 11 of 30
What is the core mechanism that allows a `reified` type parameter to be accessible at runtime in a Kotlin `inline` function?
Show the answer
Answer: a · The compiler copies the function's body and the actual type argument directly into the location where the function is called.
`reified` works because the `inline` function's body and its actual type arguments are copied directly to the call site by the compiler, thus avoiding type erasure. Option D describes a common manual workaround for type erasure, not the automated mechanism of `reified`.
Read the full bite: What is a reified type parameter in Kotlin?
Question 12 of 30
Which approach correctly gives a polymorphic Typography component type-safe props so that disabled is rejected when as is h1 but to is accepted when as is a custom Link?
Show the answer
Answer: d · constrain the generic C to React.ElementType and intersect Omit<ComponentPropsWithoutRef<C>, 'color'> with the component's own props
Option D is correct because React.ElementType accepts both intrinsic tags and custom components, ComponentPropsWithoutRef<C> surfaces the correct props for each C, and Omit resolves clashes with custom APIs like color. Option A is tempting but excludes custom components such as Link, while A and D sacrifice compile-time validation.
Read the full bite: Design a type-safe polymorphic component that renders as different HTML elements
Question 13 of 30
Which TypeScript structure should you choose to make an ApiResponse<T> that cannot simultaneously hold both data and error properties?
Show the answer
Answer: d · A union of two interfaces sharing a status literal, one generic branch with data: T and the other with error: { code; message; }
A discriminated union with a shared literal status makes it impossible to represent both states at once and enables automatic type narrowing. Option A is a common mistake because optional fields and a broad string status allow objects where both data and error are present, absent, or mismatched.
Read the full bite: Write a generic ApiResponse<T> type with success and error states
Question 14 of 30
What is the primary reason Kotlin's MutableList<E> is invariant, while List<out E> is covariant?
Show the answer
Answer: b · MutableList allows elements of type E to be both added to and retrieved from the list, requiring E to be used in both 'in' and 'out' positions.
The card explains that a generic type must remain invariant if it is used in both 'in' (consumer, like add) and 'out' (producer, like get) positions, which is precisely the case for MutableList. Option A is tempting because mutability is the context, but the direct reason for invariance is the dual usage of the generic type in 'in' and 'out' positions, as per Kotlin's variance rules.
Read the full bite: Kotlin's `in` and `out`: Declaration-Site Variance
Question 15 of 30
What is the fundamental reason Kotlin's reified type parameters are exclusively usable with inline functions?
Show the answer
Answer: c · The compiler uses inline functions to substitute the actual type argument directly into the function's bytecode at the call site.
The card states that when an inline function is called, the compiler copies its body to the call site and replaces the reified generic type with the actual type argument. This compile-time substitution is the core mechanism that inline functions enable for reified types. Option B describes a workaround that reified types aim to eliminate, not how they function with inline.
Read the full bite: Reified Type Parameters: Accessing Generic Types at Runtime
Question 16 of 30
What return type does fetchItem<T extends boolean>(..., includeHistory: T): T extends true ? ExtendedItem : BaseItem yield when includeHistory is a plain boolean variable?
Show the answer
Answer: c · The type resolves to ExtendedItem | BaseItem because boolean encompasses both true and false
Because boolean is equivalent to true | false, the distributive conditional type evaluates both branches and produces a union. Option B is tempting but wrong because TypeScript does not narrow a plain boolean variable to a literal across a function boundary.
Read the full bite: How would you model fetchItem's return type with generics and conditional types?
Question 17 of 30
Given a type `Mapish = { [k: string]: boolean; }`, what type does `keyof Mapish` evaluate to?
Show the answer
Answer: d · string | number
The card explicitly states that for a string index signature like `{ [k: string]: boolean; }`, `keyof Mapish` evaluates to `string | number`. This is due to JavaScript's runtime behavior where numeric keys are coerced to strings, which TypeScript reflects for safety. Simply `string` would be incorrect as it omits the numeric access possibility.
Question 18 of 30
What is the most significant problem that TypeScript Conditional Types are designed to solve in generic programming?
Show the answer
Answer: b · Enabling a single generic function to have a return type that adapts based on its input type, reducing the need for multiple overloads.
The card highlights that conditional types are used to model the relationship between input and output types, specifically to avoid an 'explosion of function overloads' by allowing a single generic function's return type to be dynamic. Option D is incorrect because conditional types are a compile-time construct, not a runtime mechanism for type changes.
Read the full bite: Conditional Types: Ternary Logic for Your Types
Question 19 of 30
When building a single TypeScript handler for mixed form inputs, which strategy correctly preserves type safety when extracting values from checkboxes, text inputs, and selects?
Show the answer
Answer: b · Narrow event.target with instanceof checks and branch on element.type to read .checked or .value.
Narrowing with instanceof and branching on element.type lets the compiler verify you read .checked for checkboxes and .value for other elements. Option D is tempting because it uses a union type, but reading .value from a checkbox gives the string on rather than the boolean state, breaking both type safety and runtime logic.
Read the full bite: Write a generic TypeScript handler for mixed form inputs?
Question 20 of 30
When a nil pointer is boxed into an interface{}, why does a subsequent nil check on that interface return false?
Show the answer
Answer: b · The interface value carries type information, so it is not nil
An interface{} holding a nil pointer is non-nil because it stores dynamic type metadata alongside the data pointer. Distractor D is wrong because a bare type assertion panics only when the dynamic type does not match, not when the underlying concrete value is nil.
Read the full bite: Explain Go's empty interface, safe usage, and runtime risks
Question 21 of 30
Why does the standard library make Item an associated type on Iterator rather than a generic parameter Iterator<Item>?
Show the answer
Answer: d · Because a type yields exactly one element type, so associated types keep next() inference unambiguous
Each iterator produces one element type, so an associated type uniquely determines Item and next() infers without annotation. The last option is backwards: generics, not associated types, would allow multiple impls.
Read the full bite: Associated types vs generic type parameters in traits
Question 22 of 30
In a generic fetchJson wrapper, why is it critical to check response.ok before returning res.json() as Promise<T>?
Show the answer
Answer: d · Because fetch resolves even on 4xx/5xx statuses, so skipping the check would return an error payload incorrectly typed as T.
fetch resolves successfully on HTTP error codes such as 404 or 500, so without the ok guard the caller would receive an error body wrongly typed as T. Option A is a tempting misconception because fetch only rejects on network failures, not on HTTP error statuses.
Read the full bite: Create a generic fetchJson wrapper with typed response and error handling
Question 23 of 30
Which TypeScript signature correctly refactors firstElement to preserve the array's element type while returning a single element?
Show the answer
Answer: c · function firstElement<T>(arr: T[]): T
Using T[] as the return type is a tempting mistake because it keeps the array wrapper instead of extracting the element, while any and unknown erase the specific type information entirely.
Read the full bite: Refactor a function using generics to accept any array type
Question 24 of 30
Which TypeScript signature preserves the specific input type while safely allowing access to a length property in a generic utility function?
Show the answer
Answer: a · function logLength<T extends { length: number }>(arg: T): T { console.log(arg.length); return arg; }
Option A constrains T with extends so the compiler knows length exists, yet returns T to keep the exact input type. Option B is tempting because it references the same shape, but it widens the return type and erases the original identity of arrays, strings, or custom objects.
Read the full bite: Explain generic constraints and provide a length-constrained generic example
Question 25 of 30
In getProperty<T, K extends keyof T>(obj: T, key: K), what is the effect of changing the return type from T[K] to T[keyof T]?
Show the answer
Answer: c · The return type widens to a union of all property types in T instead of the specific type for the provided key.
T[K] looks up the exact type for the specific key passed, whereas T[keyof T] resolves to a union of every property type on T because keyof T is a union of all keys. The most tempting distractor is wrong because key validation still happens at the parameter level via K extends keyof T, regardless of what the return type uses.
Read the full bite: Write a generic type-safe getProperty using keyof
Question 26 of 30
What is the main risk of declaring separate generic parameters on getState and setState instead of one class-level T?
Show the answer
Answer: b · The methods could be invoked with unrelated types, so getState and setState no longer agree on the state type.
A class-level generic binds every method to the same concrete type after instantiation, but method-level generics let getState and setState operate on unrelated types, breaking state consistency. Distractor A describes a different mistake—forgetting to type the constructor argument—not the specific consequence of scattering generics across methods.
Read the full bite: Create a generic State class with getState and setState
Question 27 of 30
What is the main type-safety benefit of making fetchJSON generic with <T> rather than having it return Promise<any>?
Show the answer
Answer: c · It lets the caller decide the expected response shape for compile-time checking without changing the wrapper code.
The generic T is supplied by the caller, allowing compile-time type checking and autocomplete without hardcoding shapes in the wrapper. C is wrong because TypeScript generics are erased at compile time and never perform runtime validation.
Read the full bite: Write a generic fetchJSON<T> wrapper and explain its type safety benefits
Question 28 of 30
Using function merge<T, U>(a: T, b: U): T & U { return { ...a, ...b }; }, what is the runtime value of a key present in both objects?
Show the answer
Answer: b · The value from b, since b is spread last and overwrites a's key
Object spread applies properties left to right, so b's value overwrites a's for shared keys at runtime. The intersection type does not merge values, and overlapping keys do not cause a compile error here.
Read the full bite: Generic merge with an intersection return type
Question 29 of 30
What is the primary type-system purpose of resolving to never in the false branch of MyReturnType<T>?
Show the answer
Answer: d · It prevents non-function types from being silently assignable by making invalid usages immediately unassignable
The never branch preserves type safety by ensuring non-function types produce an unassignable type, which stops invalid usage at compile time. Leaving the false branch as T or unknown would silently allow non-functions to pass through, a common mistake.
Read the full bite: Implement MyReturnType<T> using conditional types and infer
Question 30 of 30
What is the primary advantage of using TypeScript generics?
Show the answer
Answer: c · It enables the creation of reusable components that maintain type safety across different data types.
Generics are designed to create components that are both reusable across various data types and type-safe, ensuring type information flows from input to output. Option B describes the 'any' type, which sacrifices type safety, while generics preserve it.
Read the full bite: TypeScript Generics: Writing Functions That Adapt to Types
Could you explain these out loud?
That is what an interview actually tests. Tezvyn gives you questions like these with what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.
The iPhone app is on the way
We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.
Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.