Typeof Types
Flow's typeof type operator extracts the Flow type of a value, so you can use it as a type annotation.
1let size = 42;2let other: typeof size = 100; // type is numberWhen to use this
Use typeof to derive a type from an existing value rather than writing it manually. This is useful when a module exports a value but not its type, or when you want to keep annotations in sync with a variable's inferred type. If the type is already available as a named export, prefer importing it directly.
typeof type syntax
The typeof operator returns the Flow type of a given value to be used as a type.
1let num1 = 42;2let num2: typeof num1 = 3.14; // Works!3let num3: typeof num1 = 'world'; // Error!incompatible-typeCannot assign 'world' to num3 because string [1] is incompatible with number [2].4
5let bool1 = true;6let bool2: typeof bool1 = false; // Works!7let bool3: typeof bool1 = 42; // Error!incompatible-typeCannot assign 42 to bool3 because number [1] is incompatible with boolean [2].8
9let str1 = 'hello';10let str2: typeof str1 = 'world'; // Works!11let str3: typeof str1 = false; // Error!incompatible-typeCannot assign false to str3 because boolean [1] is incompatible with string [2].You can use any value with typeof, as long as the argument itself is a variable or member access:
1let obj1 = {foo: 1, bar: true, baz: 'three'};2let obj2: typeof obj1 = {foo: 42, bar: false, baz: 'hello'};3let num: typeof obj1.bar = 1;4
5let arr1 = [1, 2, 3];6let arr2: typeof arr1 = [3, 2, 1];7
8type T = typeof {a: 1}; // Errortypeof can only be used to get the type of variables. [ParseError]typeof inherits behaviors of inference
When you use typeof, you're taking the results of Flow's inference and
asserting it as a type. While this can be very useful, it can also lead to some
unexpected results.
For example, when you use literal values in Flow, their inferred type is the
primitive that it belongs to. Thus, the number 42 has the inferred type of
number. You can see this when you use typeof.
1let num1 = 42;2let num2: typeof num1 = 3.14; // Works!3
4let bool1 = true;5let bool2: typeof bool1 = false; // Works!6
7let str1 = 'hello';8let str2: typeof str1 = 'world'; // Works!However, this only happens with the inferred type. If you specify the literal
type, it will be used in typeof.
1let num1: 42 = 42;2let num2: typeof num1 = 3.14; // Error!incompatible-typeCannot assign 3.14 to num2 because number literal 3.14 [1] is incompatible with number literal 42 [2].3
4let bool1: true = true;5let bool2: typeof bool1 = false; // Error!incompatible-typeCannot assign false to bool2 because boolean literal false [1] is incompatible with boolean literal true [2].6
7let str1: 'hello' = 'hello';8let str2: typeof str1 = 'world'; // Error!incompatible-typeCannot assign 'world' to str2 because string literal world [1] is incompatible with string literal hello [2].typeof inherits behaviors of other types
There are many different types in Flow, some of these types behave differently than others. These differences make sense for that particular type but not for others.
When you use typeof, you're inserting another type with all of its behaviors.
This can make typeof seem inconsistent where it is not.
For example, if you use typeof with a class you need to remember that classes
are nominally typed instead of structurally typed. So that two classes with
the same exact shape are not considered equivalent.
1class MyClass {2 method(val: number) { /* ... */ }3}4
5class YourClass {6 method(val: number) { /* ... */ }7}8
9let test1: typeof MyClass = YourClass; // Error!incompatible-typeCannot assign YourClass to test1 because YourClass [1] is incompatible with MyClass [2].10let test2: typeof MyClass = MyClass; // Works!Differences from runtime typeof
JavaScript's runtime typeof operator returns a string like "number" or "object", but it can't distinguish many types — for example, objects, arrays, and null all produce "object":
typeof {foo: true} === 'object'
typeof [true, false] === 'object'
typeof null === 'object'
Flow's typeof is a type-level operator that gives you the full Flow type of a value, preserving its exact structure. It is not used at runtime — it only exists in type annotations.
See Also
- Classes —
typeofis commonly used with classes to refer to the class value (not instance) type - Modules —
typeofimports for getting the type of an imported value - Nominal & Structural Typing —
typeofwith classes preserves nominal typing behavior