Duck typing mental model in TypeScript - Time & Space Complexity
We want to see how the time it takes to check if an object fits a type grows as the object gets bigger.
How does TypeScript's duck typing affect the time it takes to verify an object's shape?
Analyze the time complexity of the following code snippet.
interface Bird {
fly(): void;
sing(): void;
}
function canFly(bird: any): bird is Bird {
return typeof bird.fly === 'function' && typeof bird.sing === 'function';
}
const obj = {
fly() { console.log('Flying'); },
sing() { console.log('Singing'); },
walk() { console.log('Walking'); }
};
canFly(obj);
This code checks if an object has the methods needed to be considered a Bird by looking at its properties.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Checking each required property on the object.
- How many times: Once per property checked (here, two properties: fly and sing).
As the number of properties to check grows, the time to verify grows linearly.
| Input Size (number of properties) | Approx. Operations |
|---|---|
| 2 | 2 checks |
| 10 | 10 checks |
| 100 | 100 checks |
Pattern observation: The time grows directly with the number of properties checked.
Time Complexity: O(n)
This means the time to check the object's shape grows in a straight line as the number of properties to check increases.
[X] Wrong: "Checking one property means constant time no matter how many properties the object has."
[OK] Correct: Even if the object is large, you must check each required property one by one, so more properties mean more checks and more time.
Understanding how duck typing checks scale helps you explain how TypeScript verifies types behind the scenes, showing your grasp of both coding and performance.
"What if we added nested objects to check inside the main object? How would the time complexity change?"
Practice
Solution
Step 1: Understand duck typing concept
Duck typing means an object is accepted if it has the needed properties or methods, regardless of its declared type.Step 2: Compare with other options
The other options describe strict or class-based typing, which is not how TypeScript works.Final Answer:
If an object has the required properties or methods, it is accepted regardless of its explicit type. -> Option BQuick Check:
Duck typing = structural compatibility [OK]
- Thinking TypeScript requires class inheritance
- Confusing runtime type checks with compile-time checks
- Assuming exact type names must match
name string property and a quack() method returning void?Solution
Step 1: Check property and method types
Thenameproperty must be a string, andquackmust be a method returning void.Step 2: Validate each option
type Duck = { name: string; quack: () => void; }; correctly definesquackas a function returning void. The other options have incorrect method signatures or return types.Final Answer:
type Duck = { name: string; quack: () => void; }; -> Option AQuick Check:
Correct method signature = type Duck = { name: string; quack: () => void; }; [OK]
- Using method return type as property type
- Confusing void and string return types
- Incorrect interface method syntax
interface Duck { name: string; quack: () => void; }
function makeItQuack(duck: Duck) {
duck.quack();
}
const obj = { name: 'Daffy', quack: () => console.log('Quack!'), swim: () => console.log('Swim') };
makeItQuack(obj);Solution
Step 1: Check if obj matches Duck interface
obj hasname(string) andquack(function returning void), so it matches by duck typing.Step 2: Call makeItQuack with obj
Callingduck.quack()runsconsole.log('Quack!'), printing "Quack!".Final Answer:
Quack! -> Option DQuick Check:
Duck typing allows extra properties, output = Quack! [OK]
- Thinking extra properties cause errors
- Expecting 'Swim' output instead of 'Quack!'
- Assuming runtime type errors
interface Duck { name: string; quack: () => void; }
const notADuck = { name: 'Donald' };
function makeItQuack(duck: Duck) {
duck.quack();
}
makeItQuack(notADuck);Solution
Step 1: Check properties of notADuck
notADuck hasnamebut lacksquackmethod required by Duck interface.Step 2: Understand TypeScript type checking
TypeScript will report an error because notADuck does not satisfy the Duck type.Final Answer:
notADuck is missing the quack method required by Duck interface. -> Option AQuick Check:
Missing required method = Type error [OK]
- Ignoring missing methods in objects
- Assuming extra properties cause errors
- Thinking TypeScript allows missing required members
interface Duck { name: string; quack: () => void; }
const a = { name: 'Daisy', quack: () => console.log('Quack!') };
const b = { name: 'Goose', quack: 'loud' };
const c = { name: 'Swan', quack: () => 'quack' };
const d = { name: 'Mallard' };
function testDuck(duck: Duck) { duck.quack(); }Which call to
testDuck will NOT cause a TypeScript error?Solution
Step 1: Check each object's quack property type
a.quack is a function returning void (correct). b.quack is a string (wrong). c.quack is a function returning string (wrong return type). d.quack is missing (wrong).Step 2: Determine which matches Duck interface
Only object a matches the Duck interface exactly.Final Answer:
testDuck(a); -> Option CQuick Check:
Correct method signature only in a [OK]
- Accepting string or wrong return type as method
- Ignoring missing methods
- Confusing method return types
Ready to prove it?
Pass the test and this pattern moves unknown
