James Forbes James Forbes - 2 months ago 12
TypeScript Question

Why can I create impossible intersection types in Typescript?

The below type definition is unimplementable, but the compiler gives me no warnings when defining it.

// No type error
type impossible = 0 & string[] & 'anything'


A value cannot be a number and string[] and a string literal.


  1. Why does typescript permit the creation of impossible types ?

  2. Is there a genuine use case for defining types that are unimplementable?


Answer

Anders Hejlsberg provided the following rationale:

It is possible to intersect primitive types (e.g. string & number), but it is not possible to actually create values of such types (other than undefined). Because such types can result from instantiation of generic types (which is performed lazily), it is not possible to consistently detect and error on the operations that create the types.

He also said in a comment on July 3, 2015:

An intersection type allows constituent types to be type parameters. Thus, you can write

declare function combine<T, U>(obj1: T, obj2: U): T & U;

This adds important new expressiveness and allows us to better model existing JS idioms. However, since type parameters can be instantiated with any type arguments, we can't upfront check whether an intersection type is "valid". Instead, we must be prepared to intersect any and all types and have "errors" surface as types for which no values are possible (e.g. string & number). You could argue that we should error when we instantiate such a type, but type instantiation in a polymorphic type system is by design heavily deferred (i.e. it happens "just in time") to avoid type explosion and our error reporting would become practically indeterminate if we went that way.

Comments