What is duck typing?
If it looks like a duck, swims like a duck, and quacks like a duck, then it probably is a duck.
Simple, right? But how it really look like? In this post, i’m gonna show you some examples of what duck typing look like in some popular language. To simplify the example, i’m going to use a simpler definition:
If it’s quacks, it’s a duck
So what if a rabbit can sound like a duck? Yeah, it’s also a duck

JS example
Dynamic typing mean that the type only matter until runtime, so as long as the variables have values satisfy some form of signatures, the program will run without problems. In Javascript for example. It’s a dynamic typing, so, it’s a duck typing language. Check example below:
function duckSound(duck) {
duck.quack()
}
var duck = {
quack() {
console.log("quack")
}
}
var rabbit = {
quack() {
console.log("quack")
}
}
duckSound(duck)
duckSound(rabbit)
Result:
❯ node duck.js
quack
quack
You can see that we can pass rabbit into duckSound and it will run fine. Why? Because the ‘rabbit’ here can quack. If it’s does sound like a duck, it’s a duck.
What about some statically typed language? In that case, can rabbit be a duck?
C# example
Ah, yes! Microsoft Java. My favorite language. It’s statically typed language. It’s OOP. It’s old. It’s enterprise. But is it duck typing?
Duck duck1 = new();
Rabbit duck2 = new();
duckSound(duck1);
// duckSound(duck2); // can't even compile
// it's quack like a duck, but it's not IDuck
void duckSound (IDuck duck) {
duck.Quack();
};
interface IDuck {
public void Quack();
}
// explicitly tell Duck is
class Duck: IDuck {
public void Quack() {
Console.WriteLine("quack");
}
}
class Rabbit {
public void Quack() {
Console.WriteLine("quack");
}
}
Like you can see above, the Rabbit cannot be a duck, even though it can quack, just like a duck. In C# we need to specify type of parameter duck in duckSound method (either Duck or IDuck), and compiler will stop you from passing rabbit into the method. But what if we let Rabbit inherit from IDuck?
class Rabbit: IDuck {
public void Quack() {
Console.WriteLine("quack");
}
}
Now we can pass rabbit into duckSound method. But we have to explicit tell the language that this Rabbit class is IDuck, then it not satisfy our definition of duck typing anymore.
If it’s quacks, it’s a duck
So, it’s not duck typing. Does that mean every statically typed language is not duck typing? I was wonder about it when i’m reading about duck typing. The answer is no. In languages like Typescript and Go, as long as struct/object satisfy the signatures of the inteface, then it is the type/inteface.
Golang example
package main
import "fmt"
// if it quacks, it's a duck
type isDuck interface {
Quack()
}
// define Duck
type Duck struct {
}
func (Duck) Quack() {
fmt.Println("quack")
}
// define "Duck"
type Rabbit struct {
}
func (Rabbit) Quack() {
fmt.Println("quack")
}
func duckSound(duck isDuck) {
duck.Quack()
}
func main() {
duck1 := Duck{}
duck2 := Rabbit{}
duckSound(duck1)
duckSound(duck2)
}
and the result
❯ go run duck.go
quack
quack
Cool, right?
Quack quack quack. Quack quack. Quack quack quack!
Secret duck in C#
Actually, in C#, you can use dynamic keyword to achieve dynamic type, and so, duck typing. Also, to use foreach, you only need type that have these conditions:
- A type has the public parameterless GetEnumerator method. The GetEnumerator method can be an extension method.
- The return type of the GetEnumerator method has the public Current property and the public parameterless MoveNext method whose return type is bool.
That’s also some kind of duck typing.