Duck typing is a style of dynamic typing where what an object can do matters more than what it is declared to be. If it has the right method, it can be used as if it were the expected type, whether or not it inherits from any particular class or declares any particular interface. The name comes from the old saying: if it walks like a duck and quacks like a duck, treat it as a duck. Python and Ruby lean on this by default; JavaScript does too, though TypeScript layers something stricter on top.
What changed in 2026
- Python Protocol classes went mainstream. Structural typing via
typing.Protocol lets type checkers such as mypy and pyright verify duck-typed code statically, without forcing inheritance from a base class. Typed Python in 2026 increasingly means duck typing with a safety net, not duck typing versus static types.
- TypeScript structural typing is now the default mental model for most JavaScript teams. A TypeScript interface is satisfied by shape, not by an explicit
implements declaration, which is duck typing checked before the code ever runs instead of while it runs.
- AI-generated code often assumes an interface without validating it. Generated Python and JavaScript frequently calls a method like
.toDict() on an argument without checking it exists first, which shows up as a runtime error more often in AI-assisted code. A defensive check at the boundary catches this early.
How duck typing works
A function that calls thing.quack() does not care whether thing is an instance of a Duck class, only that it has a quack method. Contrast this with nominal typing, where a type must explicitly declare that it implements a given interface before it is allowed to be used that way.
class Duck:
def quack(self):
return "Quack!"
class Person:
def quack(self):
return "I am pretending to be a duck!"
def make_it_quack(thing):
print(thing.quack()) # works on anything with .quack()
make_it_quack(Duck())
make_it_quack(Person())
Duck typing vs static and nominal typing
| Approach |
How type-checking works |
Example languages |
| Duck typing (dynamic) |
Checked at run time, based on available methods |
Python, Ruby, JavaScript |
| Nominal typing |
A type must explicitly declare it implements an interface |
Java in its pre-generics era, C# |
| Structural typing (static) |
Checked at compile time, based on shape, no explicit declaration needed |
TypeScript, Go interfaces |
Duck typing in JavaScript
JavaScript objects are duck typed by default at run time; nothing stops a caller from invoking any method that happens to exist. TypeScript adds structural typing on top, checked before the code ever runs, which is why much of the JavaScript ecosystem in 2026 treats TypeScript as duck typing with a compiler watching. The same shape-over-declaration idea shows up in how interfaces and abstract classes divide a contract from its implementation.
function makeItQuack(thing) {
return thing.quack(); // no type declared or checked; just called
}
Where duck typing breaks down
A large public API with many callers benefits from a documented, explicit contract; duck typing just hopes people read the source. Renaming a method silently breaks every duck-typed caller with no compiler error, only a runtime failure the next time that code path runs. An AttributeError three calls deep, caused by a caller passing the wrong kind of duck-typed object, is far harder to trace than a compile-time type error would have been.
When it is genuinely useful
Quick scripts, plugin systems built around "anything with a run method," test doubles that only need the right methods rather than a shared base class, and generic utility functions written to operate on "anything iterable" are all strong fits. The flexibility is the point in these cases, and the lack of a formal contract rarely causes problems at that scale.
FAQ
Is duck typing the same as dynamic typing?
Related but not identical. Dynamic typing generally means types are checked at run time; duck typing specifically means an object type is defined by its available methods rather than its declared class.
Does TypeScript use duck typing?
It uses structural typing, the same idea of shape over declared identity, but checked statically at compile time instead of at run time.
Is duck typing bad practice?
No, but it needs guardrails at public boundaries. Internal quick utilities are a great fit; external APIs benefit from an explicit interface or type hints.
How do I get editor autocomplete with duck typing?
Use Python Protocol classes or TypeScript interfaces to describe the expected shape without forcing inheritance, which gives back the flexibility plus editor support.
Where to go next