As a result of having weak dynamic typing, JavaScript doesn’t have any of these, you can use any type at any time.

Variance in Subclasses

To get a sense of when and why the different kinds of variance matters, let’s talk about methods of subclasses and how they get type checked.

We’ll quickly set up our BaseClass which will define just one method that accepts an input value with the type City and an returned output also with the type City.

class BaseClass {

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

}

Now, let’s walk through different definitions of method() in a couple different subclasses.

Equally specific inputs and outputs — Good

To start, we can define a SubClass that extends our BaseClass. Here you can see that the value and the return type are both City just like in BaseClass:

class SubClass extends BaseClass {

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

}

This is okay because if something else in your program is using SubClass as if it were a BaseClass, it would still be using a City and wouldn’t cause any issues.

More specific outputs — Good

Next, we’ll have a different SubClass that returns a more specific type:

class SubClass extends BaseClass {

method(value: City): SanFrancisco { ... }

}

This is also okay because if something is using SubClass as if it were a BaseClass they would still have access to the same interface as before because SanFrancisco is just a City with a little more information.

Less specific outputs — Bad

Next, we’ll have a different SubClass that returns a less specific type:

class SubClass extends BaseClass {

method(value: City): Noun { ... } // ERROR!!

}

In Flow this will cause an error because if you are expecting to get a return value of a City, you may be using something that doesn’t exist on Noun, which could easily cause an error at runtime.

Less specific inputs — Good

Next, we’ll have another SubClass that accepts a value of a less specific type.

class SubClass extends BaseClass {

method(value: Noun): City { ... }

}

This is perfectly fine because if we pass in a more specific type we’ll still have all the information we need to be compatible with Noun.

More specific inputs — Bad

Finally, we’ll have yet another SubClass that accepts a value of a more specific type.

class SubClass extends BaseClass {

method(value: SanFrancisco): City { ... } // ERROR!!

}

This is an error in Flow because if you are expecting a SanFrancisco and you get a City you could be using something that only exists on SanFrancisco which would cause an error at runtime.