What is the difference between `mixed` and `any`?

The docs say:

  • mixed: the "supertype" of all types. Any type can flow into a mixed.
  • any: the "dynamic" type. Any type can flow into any, and vice-versa

What would be a case where mixed and any cannot be used interchangeably?


The difference is the "vice-versa": any can flow into other types but mixed can not.

/* @flow */
var numeric:number = 0;
var anyTyped:any;
var mixTyped:mixed;

numeric = anyTyped;
numeric = mixTyped; // This will throw a flow check error: "Cannot assign `mixTyped` to `numeric` because mixed is incompatible with number. [incompatible-type]"

From the docs you linked to:

It is worth calling out any specifically because of the special nature of this annotation. Use any to escape the static typing of Flow. In other words, if Flow is getting in your way, and you are absolutely convinced your program is type correct, you can silence the errors by annotating locations along the error paths with type any.


"Any" supports covariance and contravariance. That's because "any" is a super-type and a subtype of all types.

Hence this works,

let genericVariable: any = 20;
let numericVariable: number;

genericVariable = numericVariable; // No error
numericVariable = genericVariable; // No error

mixed supports covariance only. It's a super-type and not a sub type of all types.

let genericVariable: mixed = 20;
let numericVariable: number;

numericVariable = genericVariable; // This shows error
genericVariable = numericVariable; // This works fine.

Covariance - Generic type (parent) could be substituted by special type (child)

Contravariance - Special type (child) could be substituted by Generic type (parent). This is a problem, unless protected by certain conventions.


When flow sees any that means you can use any type. The program is indifferent as to the parameter's type, and it will not try to infer result type. So result type will be any also.

For example, the following code will not report any errors:

// @flow
function add(one: any, two: any): number {
  return one + two;
}

add(1, 2);     // Works.
add("1", "2"); // Works.
add({}, []);   // Works.

But "mixed" type should be processed someway to infer actual type.

// @flow
function stringify(value: mixed) {
  // $ExpectError
  return "" + value; // Error!
}

stringify("foo");

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

// @flow
function stringify(value: mixed) {
  if (typeof value === 'string') {
    return "" + value; // Works!
  } else {
    return "";
  }
}

stringify("foo");