TypeScript Quality Assurance & Improvement 5 — Questions and Answers
Question 1: What is the purpose of `@ts-expect-error` compared to `@ts-ignore` in TypeScript?
- They are identical directives with different names
- `@ts-expect-error` causes a compile error if the next line does NOT have a type error, making suppression intentional (Correct answer)
- `@ts-expect-error` suppresses all errors in the entire file
- `@ts-ignore` is the newer preferred directive
Correct answer: `@ts-expect-error` causes a compile error if the next line does NOT have a type error, making suppression intentional
`@ts-expect-error` fails if the suppressed line becomes valid, so stale suppressions are caught — unlike `@ts-ignore` which silently ignores all errors.
Question 2: Which TypeScript configuration option helps detect dead code by flagging unused local variables?
- noImplicitReturns
- noUnusedLocals (Correct answer)
- strictBindCallApply
- noPropertyAccessFromIndexSignature
Correct answer: noUnusedLocals
`noUnusedLocals: true` causes the compiler to emit errors for declared local variables that are never read, helping remove dead code.
Question 3: What problem does the `Record<K, V>` utility type solve compared to an index signature `{ [key: string]: V }`?
- Record only allows string keys while index signatures allow any key type
- Record constrains keys to a specific union type, catching invalid key access at compile time (Correct answer)
- Record is mutable while index signatures are readonly
- Record disallows undefined values while index signatures permit them
Correct answer: Record constrains keys to a specific union type, catching invalid key access at compile time
`Record<'a'|'b', number>` ensures only the keys `'a'` and `'b'` are valid, while a plain index signature allows any string, providing weaker guarantees.
Question 4: In TypeScript, what is a 'branded type' and why is it useful for QA?
- A type that includes the company's trademark in its name
- A nominal type pattern using intersection with a unique symbol to prevent mixing structurally identical types (Correct answer)
- A type exported from a well-known npm brand library
- A type that is automatically validated at runtime
Correct answer: A nominal type pattern using intersection with a unique symbol to prevent mixing structurally identical types
Branded types add a phantom property to distinguish types that are structurally identical, such as `UserId` vs `OrderId`, both being `string` underneath.
Question 5: What does `isolatedModules: true` in tsconfig.json enforce and why is it a good QA practice?
- It prevents importing from node_modules
- It ensures each file can be safely transpiled independently without cross-file type info, catching re-export-only patterns (Correct answer)
- It isolates test files from production code
- It prevents circular imports between modules
Correct answer: It ensures each file can be safely transpiled independently without cross-file type info, catching re-export-only patterns
`isolatedModules` errors on constructs like `export { MyType }` that require type information to distinguish from value exports, ensuring compatibility with transpilers like Babel or esbuild.
Question 6: How can TypeScript's `Awaited<T>` utility type improve async code quality?
- It cancels a Promise automatically after a timeout
- It unwraps nested Promise types, giving the resolved value type for deeply nested async operations (Correct answer)
- It converts synchronous functions to async ones
- It marks a type as requiring await before use
Correct answer: It unwraps nested Promise types, giving the resolved value type for deeply nested async operations
`Awaited<Promise<Promise<string>>>` resolves to `string`, making generic async return type calculations accurate even with multiple levels of nesting.
Question 7: What is the benefit of using `const enum` vs regular `enum` in TypeScript, and what is a key risk?
- const enum improves type safety; the risk is it prevents all refactoring
- const enum inlines numeric values at compile time for performance; the risk is it breaks across module boundaries when using isolated transpilation (Correct answer)
- const enum adds runtime type checks; the risk is increased bundle size
- const enum allows string values; the risk is case sensitivity errors
Correct answer: const enum inlines numeric values at compile time for performance; the risk is it breaks across module boundaries when using isolated transpilation
`const enum` values are inlined as literals, eliminating the enum object at runtime, but this breaks when files are transpiled independently (e.g., with Babel or `isolatedModules`).
What is the purpose of `@ts-expect-error` compared to `@ts-ignore` in TypeScript?