Mixed Types

Typing unknown types with mixed

In general, programs have several different categories of types:

A single type:

Here the input value can only be a number.

1
2
3
function square(n: number) {
  return n * n;
}

A group of different possible types:

Here the input value could be either a string or a number.

1
2
3
function stringifyBasicValue(value: string | number) {
  return '' + value;
}

A type based on another type:

Here the return type will be the same as the type of whatever value is passed into the function.

1
2
3
function identity<T>(value: T): T {
  return value;
}

These three are the most common categories of types. They will make up the majority of the types you’ll be writing.

However, there is also a fourth category.

An arbitrary type that could be anything:

Here the passed in value is an unknown type, it could be any type and the function would still work.

1
2
3
function getTypeOf(value: mixed): string {
  return typeof value;
}

These unknown types are less common, but are still useful at times.

You should represent these values with mixed.

Anything goes in, Nothing comes out

mixed will accept any type of value. Strings, numbers, objects, functions– anything will work.

1
2
3
4
5
6
7
8
9
// @flow
function stringify(value: mixed) {
  // ...
}

stringify("foo");
stringify(3.14);
stringify(null);
stringify({});

When you try to use a value of a mixed type you must first figure out what the actual type is or you’ll end up with an error.

1
2
3
4
5
6
7
// @flow
function stringify(value: mixed) {
  // $ExpectError
  return "" + value; // Error!
}

stringify("foo");
mixed This type cannot be used in an addition because it is unknown whether it behaves like a string or a number.

Instead you must ensure the value is a certain type by refining it.

1
2
3
4
5
6
7
8
9
10
// @flow
function stringify(value: mixed) {
  if (typeof value === 'string') {
    return "" + value; // Works!
  } else {
    return "";
  }
}

stringify("foo");

Because of the typeof value === 'string' check, Flow knows the value can only be a string inside of the if statement. This is known as a refinement.