I find it weird to put `{}` together. So I figured I would change it to have an empty line and ask for feedback :)

Beware: most of the test cases are not representative of real code, you almost never define blocks with no content in practice.
605 lines
14 KiB
Plaintext
605 lines
14 KiB
Plaintext
exports[`test array_rest.js 1`] = `
|
|
"let xs = [0, \"\", true];
|
|
let [a, ...ys] = xs;
|
|
let [b, ...zs] = ys;
|
|
let c = zs[0]; // retain tuple info
|
|
let d = zs[1]; // run off the end
|
|
|
|
(a: void); // error: number ~> void
|
|
(b: void); // error: string ~> void
|
|
(c: void); // error: boolean ~> void
|
|
(d: void); // error: number|string|boolean ~> void
|
|
|
|
let [...e] = 0;
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
let xs = [ 0, \"\", true ];
|
|
let [ a, ...ys ] = xs;
|
|
let [ b, ...zs ] = ys;
|
|
let c = zs[0];
|
|
// retain tuple info
|
|
let d = zs[1];
|
|
// run off the end
|
|
(a: void);
|
|
// error: number ~> void
|
|
(b: void);
|
|
// error: string ~> void
|
|
(c: void);
|
|
// error: boolean ~> void
|
|
(d: void);
|
|
// error: number|string|boolean ~> void
|
|
let [ ...e ] = 0;
|
|
"
|
|
`;
|
|
|
|
exports[`test computed.js 1`] = `
|
|
"var { [\"key\"]: val1 } = { key: \"val\" };
|
|
(val1: void); // error: string ~> void
|
|
|
|
var key: string = \"key\";
|
|
var { [key]: val2 } = { key: \"val\" };
|
|
(val2: void); // ok (gasp!) by existing StrT -> ElemT rule
|
|
|
|
var { [\"key\"]: val3, ...spread } = { key: \"val\" };
|
|
(spread.key: void); // error (gasp!) in general we don\'t know if a computed prop should be excluded from spread
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
var { [\"key\"]: val1 } = { key: \"val\" };
|
|
(val1: void);
|
|
// error: string ~> void
|
|
var key: string = \"key\";
|
|
var { [key]: val2 } = { key: \"val\" };
|
|
(val2: void);
|
|
// ok (gasp!) by existing StrT -> ElemT rule
|
|
var { [\"key\"]: val3, ...spread } = { key: \"val\" };
|
|
(spread.key: void); // error (gasp!) in general we don\'t know if a computed prop should be excluded from spread
|
|
"
|
|
`;
|
|
|
|
exports[`test defaults.js 1`] = `
|
|
"/* @flow */
|
|
|
|
function obj_prop_fun({p:{q=0}={q:true}}={p:{q:\"\"}}) {
|
|
// errors:
|
|
// * number ~> void, from default on _.p.q
|
|
// * boolean ~> void, from default on _.p
|
|
// * string ~> void, from default on _
|
|
// * null ~> void, from call below
|
|
(q:void);
|
|
}
|
|
obj_prop_fun(); // ok
|
|
obj_prop_fun({}); // ok
|
|
obj_prop_fun({p:{}}); // ok
|
|
obj_prop_fun({p:{q:null}}); // ok, provides add\'l lower bound
|
|
|
|
function obj_prop_var(o={p:{q:\"\"}}) {
|
|
var {p:{q=0}={q:true}} = o;
|
|
// errors:
|
|
// * number ~> void, from default on o.p.q
|
|
// * boolean ~> void, from default on o.p
|
|
// * string ~> void, from default on o
|
|
// * null ~> void, from call below
|
|
(q:void);
|
|
}
|
|
obj_prop_var(); // ok
|
|
obj_prop_var({}); // ok
|
|
obj_prop_var({p:{}}); // ok
|
|
obj_prop_var({p:{q:null}}); // ok, provides add\'l lower bound
|
|
|
|
function obj_rest({p:{q,...o}={q:0,r:0}}={p:{q:0,r:\"\"}}) {
|
|
// errors:
|
|
// * number ~> void, from default on _.p
|
|
// * string ~> void, from default on _
|
|
// * null ~> void, from call below
|
|
(o.r:void);
|
|
}
|
|
obj_rest(); // ok
|
|
obj_rest({}); // ok
|
|
obj_rest({p:{}}); // ok
|
|
obj_rest({p:{q:0,r:null}});
|
|
|
|
function obj_prop_annot({
|
|
p = true // error: boolean ~> string
|
|
}: {
|
|
p: string
|
|
} = {
|
|
p: 0 // error: number ~> string
|
|
}) {
|
|
(p:void); // error: string ~> void
|
|
}
|
|
|
|
var {
|
|
p = true // error: boolean ~> string
|
|
}: {
|
|
p: string
|
|
} = {
|
|
p: 0 // error: number ~> string
|
|
};
|
|
(p:void); // error: string ~> void
|
|
|
|
function obj_prop_err({x:{y}}=null) {} // error: property \`x\` cannot be accessed on null
|
|
function obj_rest_err({...o}=0) {} // error: expected object instead of number
|
|
function arr_elem_err([x]=null) {} // error: element 0 cannot be accessed on null
|
|
function arr_rest_err([...a]=null) {} // error: expected array instead of null
|
|
|
|
function gen<T>(x:T,{p=x}:{p:T}):T {
|
|
return p;
|
|
}
|
|
|
|
// Default values in destructuring unwrap optional types
|
|
obj_prop_fun(({} : {p?:{q?:null}})); // ok
|
|
obj_prop_var(({} : {p?:{q?:null}})); // ok
|
|
|
|
// union-like upper bounds preserved through destructuring
|
|
function obj_prop_opt({p}:{p?:string}={p:0}) {}
|
|
function obj_prop_maybe({p}:{p:?string}={p:0}) {}
|
|
function obj_prop_union({p}:{p:number|string}={p:true}) {}
|
|
|
|
// TODO: union-of-objects upper bounds preserved through destructuring
|
|
function obj_prop_union2({p}:{p:number}|{p:string}={p:true}) {}
|
|
|
|
function default_expr_scope({a, b = a}) {}
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
/* @flow */
|
|
|
|
function obj_prop_fun({ p: { q = 0 } = { q: true } } = { p: { q: \"\" } }) {
|
|
// errors:
|
|
// * number ~> void, from default on _.p.q
|
|
// * boolean ~> void, from default on _.p
|
|
// * string ~> void, from default on _
|
|
// * null ~> void, from call below
|
|
(q: void);
|
|
}
|
|
obj_prop_fun();
|
|
// ok
|
|
obj_prop_fun({});
|
|
// ok
|
|
obj_prop_fun({ p: {} });
|
|
// ok
|
|
obj_prop_fun({ p: { q: null } });
|
|
// ok, provides add\'l lower bound
|
|
function obj_prop_var(o = { p: { q: \"\" } }) {
|
|
var { p: { q = 0 } = { q: true } } = o;
|
|
// errors:
|
|
// * number ~> void, from default on o.p.q
|
|
// * boolean ~> void, from default on o.p
|
|
// * string ~> void, from default on o
|
|
// * null ~> void, from call below
|
|
(q: void);
|
|
}
|
|
obj_prop_var();
|
|
// ok
|
|
obj_prop_var({});
|
|
// ok
|
|
obj_prop_var({ p: {} });
|
|
// ok
|
|
obj_prop_var({ p: { q: null } });
|
|
// ok, provides add\'l lower bound
|
|
function obj_rest(
|
|
{ p: { q, ...o } = { q: 0, r: 0 } } = { p: { q: 0, r: \"\" } }
|
|
) {
|
|
// errors:
|
|
// * number ~> void, from default on _.p
|
|
// * string ~> void, from default on _
|
|
// * null ~> void, from call below
|
|
(o.r: void);
|
|
}
|
|
obj_rest();
|
|
// ok
|
|
obj_rest({});
|
|
// ok
|
|
obj_rest({ p: {} });
|
|
// ok
|
|
obj_rest({ p: { q: 0, r: null } });
|
|
|
|
function obj_prop_annot(
|
|
{
|
|
// error: boolean ~> string
|
|
p = true
|
|
}: { p: string } = {
|
|
// error: number ~> string
|
|
p: 0
|
|
}
|
|
) {
|
|
(p: void); // error: string ~> void
|
|
}
|
|
|
|
var {
|
|
// error: boolean ~> string
|
|
p = true
|
|
}: { p: string } = {
|
|
// error: number ~> string
|
|
p: 0
|
|
};
|
|
(p: void);
|
|
// error: string ~> void
|
|
function obj_prop_err({ x: { y } } = null) {
|
|
}
|
|
// error: property \`x\` cannot be accessed on null
|
|
function obj_rest_err({ ...o } = 0) {
|
|
}
|
|
// error: expected object instead of number
|
|
function arr_elem_err([ x ] = null) {
|
|
}
|
|
// error: element 0 cannot be accessed on null
|
|
function arr_rest_err([ ...a ] = null) {
|
|
}
|
|
// error: expected array instead of null
|
|
function gen<T>(x: T, { p = x }: { p: T }): T {
|
|
return p;
|
|
}
|
|
|
|
// Default values in destructuring unwrap optional types
|
|
obj_prop_fun(({}: { p?: { q?: null } }));
|
|
// ok
|
|
obj_prop_var(({}: { p?: { q?: null } }));
|
|
// ok
|
|
// union-like upper bounds preserved through destructuring
|
|
function obj_prop_opt({ p }: { p?: string } = { p: 0 }) {
|
|
}
|
|
function obj_prop_maybe({ p }: { p: ?string } = { p: 0 }) {
|
|
}
|
|
function obj_prop_union({ p }: { p: number | string } = { p: true }) {
|
|
}
|
|
|
|
// TODO: union-of-objects upper bounds preserved through destructuring
|
|
function obj_prop_union2({ p }: { p: number } | { p: string } = { p: true }) {
|
|
}
|
|
|
|
function default_expr_scope({ a, b = a }) {
|
|
}
|
|
"
|
|
`;
|
|
|
|
exports[`test destructuring.js 1`] = `
|
|
"declare var a:string;
|
|
declare var b:string;
|
|
declare var c:string;
|
|
[{a1:a, b},c] = [{a1:0, b:1},2];
|
|
|
|
var {m} = {m:0};
|
|
({m} = {m:m});
|
|
|
|
var obj;
|
|
({n: obj.x} = {n:3});
|
|
[obj.x] = [\'foo\'];
|
|
|
|
function foo({p, z:[r]}) {
|
|
a = p;
|
|
b = z;
|
|
c = r;
|
|
}
|
|
foo({p:0, z:[1,2]});
|
|
|
|
[a,,b,...c] = [0,1,true,3];
|
|
|
|
function bar({x, ...z}) {
|
|
var o:{x: string; y: number;} = z;
|
|
}
|
|
bar({x:\"\",y:0});
|
|
|
|
var spread = {y:\"\"};
|
|
var extend: {x:number; y:string; z: boolean} = {x:0, ...spread};
|
|
|
|
function qux(_: {a:number}) { }
|
|
qux({a:\"\"});
|
|
function corge({b}: {b:string}) { }
|
|
corge({b:0});
|
|
|
|
var {n}:{n: number} = {n: \"\"}
|
|
|
|
function test() {
|
|
var {foo} = {bar: 123}; // error on foo
|
|
var {bar, baz} = {bar: 123} // error on baz
|
|
}
|
|
|
|
function test() {
|
|
var x = {foo: \'abc\', bar: 123};
|
|
var {foo, ...rest} = x;
|
|
(x.baz: string); // error, baz doesn\'t exist
|
|
(rest.baz: string); // no error, rest is unsealed
|
|
}
|
|
|
|
module.exports = corge;
|
|
|
|
class Base {
|
|
baseprop1: number;
|
|
baseprop2: number;
|
|
}
|
|
|
|
class Child extends Base {
|
|
childprop1: number;
|
|
childprop2: number;
|
|
}
|
|
|
|
var {baseprop1, childprop1, ...others} = new Child();
|
|
|
|
var bp1: number = baseprop1;
|
|
var bp1_err: string = baseprop1; // Error: number ~> string
|
|
var bp2: number = others.baseprop2;
|
|
var bp2_err: string = others.baseprop2; // Error: number ~> string
|
|
|
|
var cp1: number = childprop1;
|
|
var cp1_err: string = childprop1; // Error: number ~> string
|
|
var cp2: number = others.childprop1;
|
|
var cp2_err: string = others.childprop2; // Error: number ~> string
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
declare var a: string;
|
|
declare var b: string;
|
|
declare var c: string;
|
|
[ { a1: a, b }, c ] = [ { a1: 0, b: 1 }, 2 ];
|
|
|
|
var { m } = { m: 0 };
|
|
({ m } = { m: m });
|
|
|
|
var obj;
|
|
({ n: obj.x } = { n: 3 });
|
|
[ obj.x ] = [ \"foo\" ];
|
|
|
|
function foo({ p, z: [ r ] }) {
|
|
a = p;
|
|
b = z;
|
|
c = r;
|
|
}
|
|
foo({ p: 0, z: [ 1, 2 ] });
|
|
|
|
[ a, , b, ...c ] = [ 0, 1, true, 3 ];
|
|
|
|
function bar({ x, ...z }) {
|
|
var o: { x: string, y: number } = z;
|
|
}
|
|
bar({ x: \"\", y: 0 });
|
|
|
|
var spread = { y: \"\" };
|
|
var extend: { x: number, y: string, z: boolean } = { x: 0, ...spread };
|
|
|
|
function qux(_: { a: number }) {
|
|
}
|
|
qux({ a: \"\" });
|
|
function corge({ b }: { b: string }) {
|
|
}
|
|
corge({ b: 0 });
|
|
|
|
var { n }: { n: number } = { n: \"\" };
|
|
|
|
function test() {
|
|
var { foo } = { bar: 123 };
|
|
// error on foo
|
|
var { bar, baz } = { bar: 123 }; // error on baz
|
|
}
|
|
|
|
function test() {
|
|
var x = { foo: \"abc\", bar: 123 };
|
|
var { foo, ...rest } = x;
|
|
(x.baz: string);
|
|
// error, baz doesn\'t exist
|
|
(rest.baz: string); // no error, rest is unsealed
|
|
}
|
|
|
|
module.exports = corge;
|
|
|
|
class Base {
|
|
baseprop1: number;
|
|
baseprop2: number;
|
|
}
|
|
|
|
class Child extends Base {
|
|
childprop1: number;
|
|
childprop2: number;
|
|
}
|
|
|
|
var { baseprop1, childprop1, ...others } = new Child();
|
|
|
|
var bp1: number = baseprop1;
|
|
var bp1_err: string = baseprop1;
|
|
// Error: number ~> string
|
|
var bp2: number = others.baseprop2;
|
|
var bp2_err: string = others.baseprop2;
|
|
// Error: number ~> string
|
|
var cp1: number = childprop1;
|
|
var cp1_err: string = childprop1;
|
|
// Error: number ~> string
|
|
var cp2: number = others.childprop1;
|
|
var cp2_err: string = others.childprop2; // Error: number ~> string
|
|
"
|
|
`;
|
|
|
|
exports[`test destructuring_param.js 1`] = `
|
|
"function f(a, { b }) {
|
|
return a + b;
|
|
}
|
|
|
|
// TODO: These throw errors when parsing.
|
|
// function g(a, { a }) {
|
|
// return a;
|
|
// }
|
|
|
|
// function h({ a, { b } }, { c }, { { d } }) {
|
|
// return a + b + c + d;
|
|
// }
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
function f(a, { b }) {
|
|
return a + b;
|
|
}
|
|
// TODO: These throw errors when parsing.
|
|
// function g(a, { a }) {
|
|
// return a;
|
|
// }
|
|
// function h({ a, { b } }, { c }, { { d } }) {
|
|
// return a + b + c + d;
|
|
// }
|
|
"
|
|
`;
|
|
|
|
exports[`test eager.js 1`] = `
|
|
"var x;
|
|
({x} = null); // error, property \`x\` can not be accessed on \`null\`
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
var x;
|
|
({ x } = null); // error, property \`x\` can not be accessed on \`null\`
|
|
"
|
|
`;
|
|
|
|
exports[`test poly.js 1`] = `
|
|
"// @flow
|
|
|
|
function obj_pattern<X>({ prop } : { prop: X }) {} // prop: X
|
|
type Prop<X> = { prop: X };
|
|
function obj_pattern2<X>({ prop } : Prop<X>) {} // prop: X
|
|
|
|
function arr_pattern<X>([ elem ] : X[]) {} // elem: X
|
|
type Elem<X> = X[];
|
|
function arr_pattern2<X>([ elem ] : Elem<X>) {} // elem: X
|
|
|
|
function tup_pattern<X>([ proj ] : [X]) {} // proj: X
|
|
type Proj<X> = [X];
|
|
function tup_pattern2<X>([ proj ] : Proj<X>) {} // proj: X
|
|
|
|
function rest_antipattern<T>(...t: T) {} // nonsense
|
|
function rest_pattern<X>(...r: X[]) {} // r: X[]
|
|
|
|
function obj_rest_pattern<X>({ _, ...o } : { _: any, x: X }) { // o: { x: X }
|
|
o.x;
|
|
}
|
|
type ObjRest<X> = { _: any, x: X };
|
|
function obj_rest_pattern<X>({ _, ...o } : ObjRest<X>) { // o: { x: X }
|
|
o.x;
|
|
}
|
|
|
|
function arr_rest_pattern<X>([ _, ...a ] : [ any, X ]) { // a: [X]
|
|
a[0];
|
|
}
|
|
type ArrRest<X> = [ any, X ];
|
|
function arr_rest_pattern<X>([ _, ...a ] : ArrRest<X>) { // a: [X]
|
|
a[0];
|
|
}
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// @flow
|
|
|
|
function obj_pattern<X>({ prop }: { prop: X }) {
|
|
}
|
|
// prop: X
|
|
type Prop<X> = { prop: X };
|
|
function obj_pattern2<X>({ prop }: Prop<X>) {
|
|
}
|
|
// prop: X
|
|
function arr_pattern<X>([ elem ]: X[]) {
|
|
}
|
|
// elem: X
|
|
type Elem<X> = X[];
|
|
function arr_pattern2<X>([ elem ]: Elem<X>) {
|
|
}
|
|
// elem: X
|
|
function tup_pattern<X>([ proj ]: [X]) {
|
|
}
|
|
// proj: X
|
|
type Proj<X> = [X];
|
|
function tup_pattern2<X>([ proj ]: Proj<X>) {
|
|
}
|
|
// proj: X
|
|
function rest_antipattern<T>(...t: T) {
|
|
}
|
|
// nonsense
|
|
function rest_pattern<X>(...r: X[]) {
|
|
}
|
|
// r: X[]
|
|
function obj_rest_pattern<X>({ _, ...o }: { _: any, x: X }) {
|
|
// o: { x: X }
|
|
o.x;
|
|
}
|
|
type ObjRest<X> = { _: any, x: X };
|
|
function obj_rest_pattern<X>({ _, ...o }: ObjRest<X>) {
|
|
// o: { x: X }
|
|
o.x;
|
|
}
|
|
|
|
function arr_rest_pattern<X>([ _, ...a ]: [any, X]) {
|
|
// a: [X]
|
|
a[0];
|
|
}
|
|
type ArrRest<X> = [any, X];
|
|
function arr_rest_pattern<X>([ _, ...a ]: ArrRest<X>) {
|
|
// a: [X]
|
|
a[0];
|
|
}
|
|
"
|
|
`;
|
|
|
|
exports[`test rec.js 1`] = `
|
|
"// @flow
|
|
|
|
// Make sure that destructuring doesn\'t cause infinite loops when combined with
|
|
// funny doses of repositioning
|
|
|
|
let foo = (i: number) => [i];
|
|
|
|
const bar = (i: number) => {
|
|
[i] = foo(i);
|
|
return [i];
|
|
};
|
|
|
|
foo = (i: number) => {
|
|
return bar(i);
|
|
};
|
|
|
|
// Also make sure that the following doesn\'t loop
|
|
|
|
declare var o;
|
|
var { x: o } = o;
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// @flow
|
|
|
|
// Make sure that destructuring doesn\'t cause infinite loops when combined with
|
|
// funny doses of repositioning
|
|
|
|
let foo = (i: number) => [ i ];
|
|
|
|
const bar = (i: number) => {
|
|
[ i ] = foo(i);
|
|
return [ i ];
|
|
};
|
|
|
|
foo = (i: number) => {
|
|
return bar(i);
|
|
};
|
|
|
|
// Also make sure that the following doesn\'t loop
|
|
declare var o;
|
|
var { x: o } = o;
|
|
"
|
|
`;
|
|
|
|
exports[`test string_lit.js 1`] = `
|
|
"var { \"key\": val } = { key: \"val\" };
|
|
(val: void); // error: string ~> void
|
|
|
|
var { \"with-dash\": with_dash } = { \"with-dash\": \"motivating example\" };
|
|
(with_dash: \"motivating example\"); // ok
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
var { key: val } = { key: \"val\" };
|
|
(val: void);
|
|
// error: string ~> void
|
|
var { \"with-dash\": with_dash } = { \"with-dash\": \"motivating example\" };
|
|
(with_dash: \"motivating example\"); // ok
|
|
"
|
|
`;
|
|
|
|
exports[`test unannotated.js 1`] = `
|
|
"// @flow
|
|
|
|
var { x } = {
|
|
x: { foo: \"foo\" }
|
|
};
|
|
|
|
function bar() {
|
|
x.bar
|
|
}
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
// @flow
|
|
|
|
var { x } = { x: { foo: \"foo\" } };
|
|
|
|
function bar() {
|
|
x.bar;
|
|
}
|
|
"
|
|
`;
|