Skip to content

Commit

Permalink
Add $ElementType<A, B> type
Browse files Browse the repository at this point in the history
Reviewed By: samwgoldman

Differential Revision: D5222718

fbshipit-source-id: de926de63a6c4f42b47929bfbbc3b20f5a094777
  • Loading branch information
Caleb Meredith authored and facebook-github-bot committed Jun 12, 2017
1 parent 325c136 commit 968210c
Show file tree
Hide file tree
Showing 8 changed files with 63 additions and 1 deletion.
5 changes: 5 additions & 0 deletions src/typing/debug_js.ml
Original file line number Diff line number Diff line change
Expand Up @@ -994,6 +994,9 @@ and json_of_destructor_impl json_cx = Hh_json.(function
| PropertyType x -> JSON_Object [
"propName", JSON_String x;
]
| ElementType t -> JSON_Object [
"elementType", _json_of_t json_cx t
]
| Bind t -> JSON_Object [
"thisType", _json_of_t json_cx t
]
Expand Down Expand Up @@ -1416,6 +1419,7 @@ and dump_t_ (depth, tvars) cx t =
let string_of_destructor = function
| NonMaybeType -> "non-maybe type"
| PropertyType x -> spf "property type `%s`" x
| ElementType _ -> "element type"
| Bind _ -> "bind"
| SpreadType _ -> "spread"
in
Expand Down Expand Up @@ -1983,6 +1987,7 @@ let string_of_selector = function
let string_of_destructor = function
| NonMaybeType -> "NonMaybeType"
| PropertyType x -> spf "PropertyType %s" x
| ElementType _ -> "ElementType"
| Bind _ -> "Bind"
| SpreadType _ -> "Spread"

Expand Down
4 changes: 4 additions & 0 deletions src/typing/flow_js.ml
Original file line number Diff line number Diff line change
Expand Up @@ -6455,6 +6455,7 @@ and eval_destructor cx ~trace reason curr_t s i =
let maybe_r = replace_reason (fun desc -> RMaybe desc) reason in
UseT (UnknownUse, DefT (maybe_r, MaybeT tvar))
| PropertyType x -> GetPropT(reason, Named (reason, x), tvar)
| ElementType t -> GetElemT(reason, t, tvar)
| Bind t -> BindT(reason, mk_methodcalltype t [] tvar, true)
| SpreadType (make_exact, todo_rev) ->
let open ObjectSpread in
Expand Down Expand Up @@ -6489,6 +6490,9 @@ and subst_destructor cx force map s = match s with
| NonMaybeType
| PropertyType _
-> s
| ElementType t ->
let t_ = subst cx ~force map t in
if t_ == t then s else ElementType t_
| Bind t ->
let t_ = subst cx ~force map t in
if t_ == t then s else Bind t_
Expand Down
1 change: 1 addition & 0 deletions src/typing/gc_js.ml
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,7 @@ and gc_selector cx state = function
and gc_destructor cx state = function
| NonMaybeType -> ()
| PropertyType _ -> ()
| ElementType t -> gc cx state t
| Bind t -> gc cx state t
| SpreadType (_, ts) -> List.iter (gc cx state) ts

Expand Down
1 change: 1 addition & 0 deletions src/typing/type.ml
Original file line number Diff line number Diff line change
Expand Up @@ -803,6 +803,7 @@ module rec TypeTerm : sig
and destructor =
| NonMaybeType
| PropertyType of string
| ElementType of t
| Bind of t
| SpreadType of bool * t list

Expand Down
11 changes: 11 additions & 0 deletions src/typing/type_annotation.ml
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,17 @@ let rec convert cx tparams_map = Ast.Type.(function
error_type cx loc (FlowError.EPropertyTypeAnnot loc)
)

(* $ElementType<T, string> acts as the type of the string elements in object
type T *)
| "$ElementType" ->
check_type_param_arity cx loc typeParameters 2 (fun () ->
let ts = convert_type_params () in
let t = List.nth ts 0 in
let e = List.nth ts 1 in
EvalT (t, TypeDestructorT
(mk_reason (RCustom "element type") loc, ElementType e), mk_id())
)

(* $NonMaybeType<T> acts as the type T without null and void *)
| "$NonMaybeType" ->
check_type_param_arity cx loc typeParameters 1 (fun () ->
Expand Down
1 change: 1 addition & 0 deletions src/typing/type_visitor.ml
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ class ['a] t = object(self)
method private destructor cx acc = function
| NonMaybeType -> acc
| PropertyType _ -> acc
| ElementType t -> self#type_ cx acc t
| Bind t -> self#type_ cx acc t
| SpreadType (_, ts) -> self#list (self#type_ cx) acc ts

Expand Down
23 changes: 23 additions & 0 deletions tests/type-destructors/element_type.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
type BadArity = $ElementType<number, number, number>;

type Arr = Array<number>;
type Arr_Elem = $ElementType<Arr, number>;

(42: Arr_Elem); // OK: `Arr_Elem` is `number`
('hello world': Arr_Elem);

function foo(a: Arr): $ElementType<Arr, number> {
if (false) return a[0];
else return 0;
}

type Obj = { [key: string]: number };
type Obj_Elem = $ElementType<Obj, string>;

(42: Obj_Elem); // OK: `Obj_Elem` is `number`
('hello world': Obj_Elem);

function bar(o: Obj): $ElementType<Obj, string> {
if (false) return o['buz'];
else return 0;
}
18 changes: 17 additions & 1 deletion tests/type-destructors/type-destructors.exp
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
element_type.js:1
1: type BadArity = $ElementType<number, number, number>;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Incorrect number of type parameters (expected 2)

element_type.js:7
7: ('hello world': Arr_Elem);
^^^^^^^^^^^^^ string. This type is incompatible with
7: ('hello world': Arr_Elem);
^^^^^^^^ number

element_type.js:18
18: ('hello world': Obj_Elem);
^^^^^^^^^^^^^ string. This type is incompatible with
18: ('hello world': Obj_Elem);
^^^^^^^^ number

non_maybe_type.js:5
5: else return 0; // this should be an error
^ number. This type is incompatible with
Expand Down Expand Up @@ -95,4 +111,4 @@ union.js:4
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ string


Found 7 errors
Found 10 errors

0 comments on commit 968210c

Please sign in to comment.