Skip to content

Commit

Permalink
nuke RecordT
Browse files Browse the repository at this point in the history
Summary: $Record types were experimental, and kind of rotting as a third object-like
def type besides ObjT and InstanceT.

It turns out that its functionality can be covered by $Enum and dict types.
So there is no use for it.

In fact, using $Enum and dict types, you can get better $Record types because
you can also specify the value type!

Also simplified type of propTypes to Object.
With this diff we could replace it with $Subtype<{[key: $Enum<P>]: any]}>.
But in a follow-up diff, we're going to make propTypes allow spreads etc.
which may interfere with such a type. Moving forward ES6 React doesn't have a
good story around propTypes anyway, and for legacy React that annotation is
not even touched, so Object should really be enough.

Reviewed By: @mroch

Differential Revision: D2132989
  • Loading branch information
avikchaudhuri authored and facebook-github-bot-7 committed Jun 6, 2015
1 parent f4178d5 commit 6d4447b
Show file tree
Hide file tree
Showing 8 changed files with 41 additions and 56 deletions.
2 changes: 1 addition & 1 deletion lib/react.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ declare class ReactComponent<D, P, S> {
componentWillUnmount(): void;
isMounted(): bool;

static propTypes: $Supertype<$Record<P>>;
static propTypes: $Subtype<{[_: $Enum<P>]: any}>; //object whose keys are in P
static contextTypes: any;
static childContextTypes: any;
static displayName: string;
Expand Down
12 changes: 1 addition & 11 deletions src/typing/constraint_js.ml
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,6 @@ module Type = struct

(* collects the keys of an object *)
| EnumT of reason * t
(* constrains the keys of an object *)
| RecordT of reason * t

(* type aliases *)
| TypeT of reason * t
Expand Down Expand Up @@ -711,7 +709,6 @@ let string_of_ctor = function
| ShapeT _ -> "ShapeT"
| DiffT _ -> "DiffT"
| EnumT _ -> "EnumT"
| RecordT _ -> "RecordT"
| KeyT _ -> "KeyT"
| HasT _ -> "HasT"
| ElemT _ -> "ElemT"
Expand Down Expand Up @@ -841,7 +838,6 @@ let rec reason_of_t = function
-> reason_of_t t

| EnumT (reason, _)
| RecordT (reason, _)
->
reason

Expand Down Expand Up @@ -985,7 +981,6 @@ let rec mod_reason_of_t f = function
| DiffT (t1, t2) -> DiffT (mod_reason_of_t f t1, t2)

| EnumT (reason, t) -> EnumT (f reason, t)
| RecordT (reason, t) -> RecordT (f reason, t)

| KeyT (reason, t) -> KeyT (f reason, t)
| HasT (reason, t) -> HasT (f reason, t)
Expand Down Expand Up @@ -1205,9 +1200,6 @@ let rec type_printer override fallback enclosure cx t =
| AnyFunT _ ->
"Function"

| RecordT (_, t) ->
spf "$Record<%s>" (pp EnclosureNone cx t)

| t ->
fallback t

Expand Down Expand Up @@ -1356,8 +1348,7 @@ let rec _json_of_t stack cx t = Json.(
"type2", _json_of_t stack cx t2
]

| EnumT (_, t)
| RecordT (_, t) -> [
| EnumT (_, t) -> [
"type", _json_of_t stack cx t
]

Expand Down Expand Up @@ -1885,7 +1876,6 @@ let rec is_printed_type_parsable_impl weak cx enclosure = function
| TypeT (_, t)
| LowerBoundT t
| UpperBoundT t
| RecordT (_, t)
| ClassT t
when weak
->
Expand Down
1 change: 0 additions & 1 deletion src/typing/constraint_js.mli
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ module Type :
| DiffT of t * t

| EnumT of reason * t
| RecordT of reason * t

| TypeT of reason * t
| BecomeT of reason * t
Expand Down
37 changes: 1 addition & 36 deletions src/typing/flow_js.ml
Original file line number Diff line number Diff line change
Expand Up @@ -689,12 +689,6 @@ and ground_type_impl cx ids t = match t with
| DiffT (t1, t2) ->
DiffT (ground_type_impl cx ids t1, ground_type_impl cx ids t2)

| RecordT (_, t) ->
RecordT (
reason_of_string "record",
ground_type_impl cx ids t
)

| _ -> assert false (** TODO **)

and lookup_type_ cx ids id =
Expand Down Expand Up @@ -796,9 +790,6 @@ let rec normalize_type cx t =
| DiffT (t1, t2) ->
DiffT (normalize_type cx t1, normalize_type cx t2)

| RecordT (r, t) ->
RecordT (r, normalize_type cx t)

(* TODO: Normalize all types? *)
| t -> t

Expand Down Expand Up @@ -968,9 +959,6 @@ let rec printify_type cx t =
| DiffT (t1, t2) ->
DiffT (printify_type cx t1, printify_type cx t2)

| RecordT (r, t) ->
RecordT (r, printify_type cx t)

| t -> t

let printified_type cx t =
Expand Down Expand Up @@ -1105,9 +1093,6 @@ let rec assert_ground ?(infer=false) cx ids = function
| EnumT(reason,t) ->
assert_ground cx ids t

| RecordT(reason,t) ->
assert_ground cx ids t

| CJSExportDefaultT (reason,t) ->
assert_ground ~infer:true cx ids t

Expand Down Expand Up @@ -2577,15 +2562,6 @@ let rec __flow cx (l, u) trace =
| (EnumT (reason1, o1), _) ->
rec_flow cx trace (o1, KeyT (reason1, u))

| (_, RecordT (reason2, o2)) ->
rec_flow cx trace (o2, KeyT(reason2, EnumT(reason2, l)))

| (RecordT (reason, o2),
(HasT(_,x) |
LookupT(_,_,x,_) | GetT(_,x,_) | SetT(_,x,_) | MethodT(_,x,_,_,_,_)))
->
rec_flow cx trace (o2, HasT(reason_of_t u,x))

| (ObjT (reason_o, { props_tmap = mapr; _ }), HasT(reason_op, x)) ->
if has_prop cx mapr x then ()
else
Expand All @@ -2609,9 +2585,6 @@ let rec __flow cx (l, u) trace =
(reason_op, reason_o)
)

| (RecordT (reason, o2), KeyT(reason_, key)) ->
rec_flow cx trace (o2, KeyT(reason_, key))

| (ObjT (reason, { props_tmap = mapr; _ }), KeyT(_,key)) ->
iter_props cx mapr (fun x tv ->
let t = StrT (reason, Some x) in
Expand All @@ -2627,11 +2600,6 @@ let rec __flow cx (l, u) trace =
rec_flow cx trace (t, key)
)

| (RecordT (reason, o2), (ObjT _ | InstanceT _)) ->
let tvar = mk_tvar cx reason in
rec_flow cx trace (u, KeyT(reason, tvar));
rec_flow cx trace (tvar, EnumT(reason, o2))

(*********************)
(* functions statics *)
(*********************)
Expand Down Expand Up @@ -2895,7 +2863,7 @@ and numeric = function
| _ -> false

and object_like = function
| ObjT _ | InstanceT _ | RecordT _ -> true
| ObjT _ | InstanceT _ -> true
| t -> function_like t

and object_like_op = function
Expand Down Expand Up @@ -3116,9 +3084,6 @@ and subst cx ?(force=true) (map: Type.t SMap.t) t =
| EnumT(reason, t) ->
EnumT(reason, subst cx ~force map t)

| RecordT(reason, t) ->
RecordT(reason, subst cx ~force map t)

| ObjAssignT(reason, t1, t2, xs, resolve) ->
ObjAssignT(reason, subst cx ~force map t1, subst cx ~force map t2, xs, resolve)

Expand Down
7 changes: 0 additions & 7 deletions src/typing/type_inference_js.ml
Original file line number Diff line number Diff line change
Expand Up @@ -625,13 +625,6 @@ let rec convert cx map = Ast.Type.(function
EnumT (mk_reason "enum type" loc, t)
)

(* $Record<T> is the type of objects whose keys are those of T *)
| "$Record" ->
check_type_param_arity cx loc typeParameters 1 (fun () ->
let t = convert cx map (List.hd typeParameters) in
RecordT (mk_reason "record type" loc, t)
)

(* $Exports<'M'> is the type of the exports of module 'M' *)
(** TODO: use `import typeof` instead when that lands **)
| "$Exports" ->
Expand Down
Empty file added tests/record/.flowconfig
Empty file.
18 changes: 18 additions & 0 deletions tests/record/record.exp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@

test.js:4:8,9: string
This type is incompatible with
test.js:2:23,28: number

test.js:7:1,6: property name "qux" is a string
This type is incompatible with
test.js:1:13,25: union type

test.js:13:1,6: string literal qux
Property not found in
test.js:9:10,29: object type

test.js:19:6,34: string literal qux
Property not found in
test.js:18:19,44: object type

Found 4 errors
20 changes: 20 additions & 0 deletions tests/record/test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
type Key1 = 'foo' | 'bar'; // make an enum type with known key set
var o1: {[key: Key1]: number} = {
foo: 0,
bar: "", // error: string ~/~ number
};
o1.foo; // OK
o1.qux; // error: qux not found

type R = {foo: any, bar: any};
type Key2 = $Enum<R>; // another way to make an enum type, with unknown key set
var o2: {[key: Key2]: number} = { foo: 0 }; // OK to leave out bar
o2.bar; // OK to access bar
o2.qux; // error: qux not found

class C<X> {
x: $Subtype<{[key: $Enum<X>]: any}>; // object with larger key set than X's
}
class D extends C<{foo: number, bar: string}> {
x: { foo: number, qux: boolean }; // error: qux not found
}

0 comments on commit 6d4447b

Please sign in to comment.