Why Typescript return type void in interface doesn’t trigger error in implementation?

The inferred type of the method without the explicit type declaration is HumanOne.speak(): string. This is compatible with void, which has two meanings:

  • in a function implementation with return type void, it means that it doesn’t return anything, more or less equivalent to specifying undefined as a return type.
  • in a function type declaration, void means that anything can be returned, and that the return value of calls must not be used. It’s more or less equivalent to unknown as far as type compatibility is concerned (but unlike unknown, you can’t really pass around values of type void).

This second meaning is also what is relevant for the subtype checking of HumanOne implements Person – the type () => string is a subtype (or: assignable to) type () => void. If you call Person.speak(), you must ignore the return value (and it might be undefined, a string, or anything else); if you call HumanOne.speak() you’ll know that you get a string back.

This is very much by design, see the docs on Return type
void
and the FAQ entry “Why are functions returning non-void assignable to function returning void?.

Leave a Comment