TypeScript Interview Patterns 🎯
Master the Most Asked TypeScript Topics
Imagine you’re a detective. Your job? Finding bugs before they cause trouble. TypeScript is your magnifying glass—it helps you spot problems before your code even runs!
Today, we’ll explore the most common interview questions about TypeScript. By the end, you’ll feel like a TypeScript superhero! 🦸
🔴 Common Type Errors
What Are Type Errors?
Think of types like labels on containers. If you put milk in a box labeled “toys,” that’s confusing! Type errors happen when you put the wrong thing in the wrong container.
The Top 5 Type Errors You’ll See
1. Type ‘X’ is not assignable to type ‘Y’
// ❌ Error: You said "number"
// but gave it "hello"
let age: number = "hello";
// ✅ Fixed
let age: number = 25;
Why it happens: You promised one type but gave another.
2. Property ‘X’ does not exist on type ‘Y’
// ❌ Error: "name" doesn't exist
// on empty object
let user = {};
console.log(user.name);
// ✅ Fixed: Define the shape first
let user = { name: "Alex" };
console.log(user.name);
3. Object is possibly ‘undefined’
// ❌ Error: items might be empty
let items: string[] | undefined;
console.log(items.length);
// ✅ Fixed: Check first!
if (items) {
console.log(items.length);
}
4. Cannot find name ‘X’
// ❌ Error: TypeScript doesn't
// know what "myVar" is
console.log(myVar);
// ✅ Fixed: Declare it first
let myVar = "exists now!";
console.log(myVar);
5. Argument type mismatch
// ❌ Error: Function expects number,
// you gave string
function double(n: number) {
return n * 2;
}
double("five");
// ✅ Fixed
double(5); // Returns 10
🧩 Type Challenge Patterns
Type challenges are like puzzles! Let’s learn the patterns that solve most of them.
Pattern 1: Extract and Pick
Problem: Get only some properties from a type.
type User = {
id: number;
name: string;
email: string;
};
// Pick only what you need
type UserPreview = Pick<User,
"id" | "name"
>;
// Result: { id: number; name: string }
Pattern 2: Conditional Types
Problem: Choose type based on condition.
// If T is string, return "yes"
// Otherwise return "no"
type IsString<T> =
T extends string ? "yes" : "no";
type A = IsString<"hello">; // "yes"
type B = IsString<42>; // "no"
Pattern 3: Mapped Types
Problem: Transform all properties.
// Make all properties optional
type MakeOptional<T> = {
[K in keyof T]?: T[K];
};
type User = { name: string; age: number };
type PartialUser = MakeOptional<User>;
// { name?: string; age?: number }
Pattern 4: Infer Keyword
Problem: Extract type from inside another type.
// Get the return type of a function
type GetReturn<T> =
T extends (...args: any[]) => infer R
? R
: never;
type Fn = () => string;
type Result = GetReturn<Fn>; // string
🎭 When to Use any Safely
any is like a “skip inspection” pass. Use it rarely and carefully!
✅ Safe Times to Use any
1. Migrating JavaScript to TypeScript
// Temporary during migration
let oldLibraryData: any =
legacyFunction();
2. Third-party libraries without types
// No types available yet
declare const untypedLib: any;
3. Truly dynamic data you’ll validate
function parseJSON(json: string): any {
// You'll validate this later
return JSON.parse(json);
}
❌ Never Use any For
- Function parameters (use generics instead)
- Return types (be explicit)
- Avoiding fixing real errors
💡 Better Alternatives
// Instead of any, use unknown
let data: unknown = fetchData();
// You MUST check before using
if (typeof data === "string") {
console.log(data.toUpperCase());
}
🏛️ Abstract Class vs Interface
This is like asking: “Toolbox vs Blueprint?”
Interface = Blueprint 📋
An interface says what must exist. It’s a contract.
interface Animal {
name: string;
speak(): void;
}
// Must have name and speak
class Dog implements Animal {
name = "Buddy";
speak() {
console.log("Woof!");
}
}
Abstract Class = Partial Building 🏗️
An abstract class can include actual code you inherit.
abstract class Animal {
// Real code you inherit
move() {
console.log("Moving...");
}
// Must be implemented
abstract speak(): void;
}
class Cat extends Animal {
speak() {
console.log("Meow!");
}
}
const cat = new Cat();
cat.move(); // Works! Inherited
cat.speak(); // "Meow!"
Quick Decision Guide
graph TD A["Need shared code?"] -->|Yes| B["Abstract Class"] A -->|No| C["Interface"] B --> D["Can have constructors"] B --> E["Can have default methods"] C --> F["Multiple interfaces allowed"] C --> G["Lighter, no runtime cost"]
| Feature | Interface | Abstract Class |
|---|---|---|
| Multiple inheritance | ✅ Yes | ❌ No |
| Default implementation | ❌ No | ✅ Yes |
| Runtime cost | None | Some |
| Properties | Types only | Actual values |
🔍 Debugging Type Errors
When TypeScript shows a red squiggly line, don’t panic! Here’s your debugging toolkit.
Step 1: Read the Error Carefully
Type 'string' is not assignable
to type 'number'.
This tells you: Expected number, got string.
Step 2: Hover for Details
In VS Code, hover over the error. You’ll see:
- What type was expected
- What type you provided
- Where it went wrong
Step 3: Use Type Assertions Wisely
// When YOU know better than TS
const input = document
.getElementById("age") as
HTMLInputElement;
// Now TS knows it's an input
console.log(input.value);
Step 4: Break Down Complex Types
// Hard to debug
type Result = Omit<
Pick<User, "id" | "data">,
"data"
> & { extra: string };
// Easier: step by step
type Step1 = Pick<User, "id" | "data">;
type Step2 = Omit<Step1, "data">;
type Result = Step2 & { extra: string };
Step 5: Use // @ts-expect-error
// When testing error cases
// @ts-expect-error Testing bad input
myFunction("wrong type");
✨ TypeScript Best Practices
1. Be Explicit, Not Lazy
// ❌ Vague
function getData(input: any): any
// ✅ Clear
function getData(id: number): User
2. Use Strict Mode
In tsconfig.json:
{
"compilerOptions": {
"strict": true
}
}
3. Prefer unknown Over any
// ❌ Dangerous
let x: any = fetchData();
x.whatever(); // No error!
// ✅ Safe
let x: unknown = fetchData();
// Must check type first!
if (typeof x === "object") {
// Now safe to use
}
4. Use Utility Types
// Don't recreate the wheel!
Partial<T> // All optional
Required<T> // All required
Readonly<T> // Can't modify
Pick<T, K> // Select properties
Omit<T, K> // Remove properties
5. Name Things Clearly
// ❌ Confusing
type T = { n: string; a: number };
// ✅ Clear
type Person = {
name: string;
age: number
};
6. Document Complex Types
/**
* User data returned from API
* @property id - Unique identifier
* @property email - User's email
*/
type User = {
id: number;
email: string;
};
🎯 Summary
You’ve learned the 6 essential interview patterns:
- Common Errors - Know them, fix them fast
- Type Challenges - Pick, Conditional, Mapped, Infer
- Using
any- Only when truly needed - Abstract vs Interface - Code sharing vs contracts
- Debugging - Read, hover, break down, assert
- Best Practices - Strict, explicit, clear
🚀 You’ve Got This!
TypeScript might seem strict, but it’s like a helpful friend saying “Hey, are you sure about that?” before you make a mistake.
With these patterns in your toolkit, you’re ready to ace any TypeScript interview! Remember: every expert was once a beginner. Keep practicing, and you’ll master TypeScript in no time! 💪
