Type Systems: Covariance, Contravariance, Bivariance, and Invariance explained

class Noun {}
class City extends Noun {}
class SanFrancisco extends City {}

Invariance

function method(value: Invariant<City>) {...}method(new Noun());         // error...
method(new City()); // okay
method(new SanFrancisco()); // error...

Covariance

function method(value: Covariant<City>) {...}method(new Noun());         // error...
method(new City()); // okay
method(new SanFrancisco()); // okay

Contravariance

function method(value: Contravariant<City>) {...}method(new Noun());         // okay
method(new City()); // okay
method(new SanFrancisco()); // error...

Bivariance

function method(value: Bivariant<City>) {...}method(new Noun());         // okay
method(new City()); // okay
method(new SanFrancisco()); // okay

Variance in Subclasses

class BaseClass {
method(value: City): City { ... }
}

Equally specific inputs and outputs — Good

class SubClass extends BaseClass {
method(value: City): City { ... }
}

More specific outputs — Good

class SubClass extends BaseClass {
method(value: City): SanFrancisco { ... }
}

Less specific outputs — Bad

class SubClass extends BaseClass {
method(value: City): Noun { ... } // ERROR!!
}

Less specific inputs — Good

class SubClass extends BaseClass {
method(value: Noun): City { ... }
}

More specific inputs — Bad

class SubClass extends BaseClass {
method(value: SanFrancisco): City { ... } // ERROR!!
}

 by the author.

--

--

--

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Jamie Kyle

Jamie Kyle

More from Medium

PageItems differences

Let’s Make 2048 (Part 1)

.toBe or .toEqual?

Server-Side Events as Simple Alternative to WebSockets