diff --git a/tests/flow/new_spread/__snapshots__/jsfmt.spec.js.snap b/tests/flow/new_spread/__snapshots__/jsfmt.spec.js.snap new file mode 100644 index 00000000..27be1b20 --- /dev/null +++ b/tests/flow/new_spread/__snapshots__/jsfmt.spec.js.snap @@ -0,0 +1,646 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`type.js 1`] = ` +"declare class T {} +declare var x: T; + +declare class U {} +declare var y: U; + +declare var nil: {||}; + +// inexact: \`p\` may be non-own +type O1 = {...{p:T}}; +declare var o1: O1; +(o1: {p?:T}); // ok +(o1: {p:T}); // error: o1.p is optional +({}: O1); // ok +({p:x}: O1); // ok +({p:y}: O1); // error: y ~> T +({p:x,q:y}: O1); // ok + +// inexact: optional \`p\`, if own, must be \`T\` +type O2 = {...{p?:T}}; +declare var o2: O2; +(o2: {p?:T}); // ok +(o2: {p:T}); // error: o2.p is optional +({}: O2); // ok +({p:x}: O2); // ok +({p:y}: O2); // error: y ~> T +({p:x,q:y}: O2); // ok + +// can't make exact from inexact +type O3 = {|...{p:T}|}; // error: spread result is not exact + +// exact +type O4 = {...{|p:T|}}; +declare var o4: O4; +(o4: {p:T}); // ok +(o4: {|p:T|}); // error: not exact +({}: O4); // error: property \`p\` not found +({p:x}: O4); // ok +({p:y}: O4); // error: y ~> T +({p:x,q:y}: O4); // ok + +// can make exact from exact +type O5 = {|...{|p:T|}|}; +declare var o5: O5; +(o5: {p:T}); // ok +(o5: {|p:T|}); // ok +(nil: O5); // error: property \`p\` not found +({p:x}: O5); // ok +({p:y}: O5); // error: y ~> T +({p:x,q:y}: O5); // error: additional property \`q\` found + +// inexact p + exact p +type O6 = {...{p:T},...{|p:U|}}; +declare var o6: O6; +(o6: {p:U}); // ok +({}: O6); // error: property \`p\` not found +({p:x}: O6); // error: x ~> U +({p:y}: O6); // ok +({p:y,q:x}: O6); // ok + +// inexact p + exact p ~> exact +type O7 = {|...{p:T},...{|p:U|}|}; // error: spread result is not exact + +// exact p + inexact p +type O8 = {...{|p:T|},...{p:U}}; +declare var o8: O8; +(o8: {p:T|U}); // ok +(o8.p: T); // error: U ~> T +(o8.p: U); // error: T ~> U + +// inexact p + exact q +type O9 = {...{p:T},...{|q:U|}}; +declare var o9: O9; +(o9: {p?:T,q:U}); +(o9.p: T); // error: o9.p is optional +(o9.q: U); // ok + +// exact p + inexact q +type O10 = {...{|p:T|},...{q:U}}; +declare var o10: O10; +(o10: {p:mixed, q?: U}); // ok + +// inexact p + inexact q +type O11 = {...{p:T},...{q:U}}; +declare var o11: O11; +(o11: {p:mixed, q: mixed}); // ok + +// exact + exact +type O12 = {...{|p:T|},...{|q:U|}}; +declare var o12: O12; +(o12: {p:T,q:U}); // ok +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +declare class T {} +declare var x: T; + +declare class U {} +declare var y: U; + +declare var nil: {||}; + +// inexact: \`p\` may be non-own +type O1 = { ...{ p: T } }; +declare var o1: O1; +(o1: { p?: T }); // ok +(o1: { p: T }); // error: o1.p is optional +({}: O1); // ok +({ p: x }: O1); // ok +({ p: y }: O1); // error: y ~> T +({ p: x, q: y }: O1); // ok + +// inexact: optional \`p\`, if own, must be \`T\` +type O2 = { ...{ p?: T } }; +declare var o2: O2; +(o2: { p?: T }); // ok +(o2: { p: T }); // error: o2.p is optional +({}: O2); // ok +({ p: x }: O2); // ok +({ p: y }: O2); // error: y ~> T +({ p: x, q: y }: O2); // ok + +// can't make exact from inexact +type O3 = {| ...{ p: T } |}; // error: spread result is not exact + +// exact +type O4 = { ...{| p: T |} }; +declare var o4: O4; +(o4: { p: T }); // ok +(o4: {| p: T |}); // error: not exact +({}: O4); // error: property \`p\` not found +({ p: x }: O4); // ok +({ p: y }: O4); // error: y ~> T +({ p: x, q: y }: O4); // ok + +// can make exact from exact +type O5 = {| ...{| p: T |} |}; +declare var o5: O5; +(o5: { p: T }); // ok +(o5: {| p: T |}); // ok +(nil: O5); // error: property \`p\` not found +({ p: x }: O5); // ok +({ p: y }: O5); // error: y ~> T +({ p: x, q: y }: O5); // error: additional property \`q\` found + +// inexact p + exact p +type O6 = { ...{ p: T }, ...{| p: U |} }; +declare var o6: O6; +(o6: { p: U }); // ok +({}: O6); // error: property \`p\` not found +({ p: x }: O6); // error: x ~> U +({ p: y }: O6); // ok +({ p: y, q: x }: O6); // ok + +// inexact p + exact p ~> exact +type O7 = {| ...{ p: T }, ...{| p: U |} |}; // error: spread result is not exact + +// exact p + inexact p +type O8 = { ...{| p: T |}, ...{ p: U } }; +declare var o8: O8; +(o8: { p: T | U }); // ok +(o8.p: T); // error: U ~> T +(o8.p: U); // error: T ~> U + +// inexact p + exact q +type O9 = { ...{ p: T }, ...{| q: U |} }; +declare var o9: O9; +(o9: { p?: T, q: U }); +(o9.p: T); // error: o9.p is optional +(o9.q: U); // ok + +// exact p + inexact q +type O10 = { ...{| p: T |}, ...{ q: U } }; +declare var o10: O10; +(o10: { p: mixed, q?: U }); // ok + +// inexact p + inexact q +type O11 = { ...{ p: T }, ...{ q: U } }; +declare var o11: O11; +(o11: { p: mixed, q: mixed }); // ok + +// exact + exact +type O12 = { ...{| p: T |}, ...{| q: U |} }; +declare var o12: O12; +(o12: { p: T, q: U }); // ok +" +`; + +exports[`type_any.js 1`] = ` +"type O1 = {...any}; +var o1: O1 = (0: mixed); // ok +(o1: empty); // ok + +type O2 = {...Object}; +var o2: O2 = (0: mixed); // ok +(o2: empty); // ok + +declare var Base: any; +declare class Derived extends Base {} +type O3 = {...Derived}; +var o3: O3 = (0: mixed); // ok +(o3: empty) // ok +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +type O1 = { ...any }; +var o1: O1 = (0: mixed); // ok +(o1: empty); // ok + +type O2 = { ...Object }; +var o2: O2 = (0: mixed); // ok +(o2: empty); // ok + +declare var Base: any; +declare class Derived extends Base {} +type O3 = { ...Derived }; +var o3: O3 = (0: mixed); // ok +(o3: empty); // ok +" +`; + +exports[`type_contra.js 1`] = ` +"declare class T {}; + +type O1 = {...{-p:T}}; +declare var o1: O1; +(o1: {p?:mixed}); // ok +(o1: {p?:T}); // error: unknown ~> T +(o1.p: T); // errors: undefined ~> T, unknown ~> T + +type O2 = {...{-[string]:T}}; +declare var o2: O2; +(o2: {[string]:mixed}); // ok +(o2: {[string]:T}); // error: unknown ~> T +(o2.p: T); // errors: unknown ~> T +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +declare class T {} + +type O1 = { ...{ -p: T } }; +declare var o1: O1; +(o1: { p?: mixed }); // ok +(o1: { p?: T }); // error: unknown ~> T +(o1.p: T); // errors: undefined ~> T, unknown ~> T + +type O2 = { ...{ -[string]: T } }; +declare var o2: O2; +(o2: { [string]: mixed }); // ok +(o2: { [string]: T }); // error: unknown ~> T +(o2.p: T); // errors: unknown ~> T +" +`; + +exports[`type_dict.js 1`] = ` +"declare class T {} +declare class U {} + +declare var o1: {...{[string]:T},...{p:U}}; +(o1: {p?:T|U,[string]:T}); // ok + +declare var o2: {...{p:T},...{[string]:U}}; +(o2: {p?:T|U,[string]:U}); // ok + +declare var o3: {...{[string]:T},...{[string]:U}}; +(o3: {[string]:T|U}); // ok + +declare var o4: {...{|[string]:T|},...{p:U}}; +(o4: {p?:T|U,[string]:T}); // ok + +declare var o5: {...{|p:T|},...{[string]:U}}; +(o5: {p:T|U,[string]:U}); // ok + +declare var o6: {...{|[string]:T|},...{[string]:U}}; +(o6: {[string]:T|U}); // ok + +declare var o7: {...{[string]:T},...{|p:U|}}; +(o7: {p:U,[string]:T}); // ok + +declare var o8: {...{p:T},...{|[string]:U|}}; +(o8: {p?:T|U,[string]:U}); // ok + +declare var o9: {...{[string]:T},...{|[string]:U|}}; +(o9: {[string]:T|U}); // ok + +declare var o10: {...{|[string]:T|},...{|p:U|}}; +(o10: {|p:U,[string]:T|}); // ok + +declare var o11: {...{|p :T|},...{|[string]:U|}}; +(o11: {|p:T|U,[string]:U|}); // ok + +declare var o12: {...{|[string]:T|},...{|[string]:U|}}; +(o12: {|[string]:T|U|}); // ok +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +declare class T {} +declare class U {} + +declare var o1: { ...{ [string]: T }, ...{ p: U } }; +(o1: { [string]: T, p?: T | U }); // ok + +declare var o2: { ...{ p: T }, ...{ [string]: U } }; +(o2: { [string]: U, p?: T | U }); // ok + +declare var o3: { ...{ [string]: T }, ...{ [string]: U } }; +(o3: { [string]: T | U }); // ok + +declare var o4: { ...{| [string]: T |}, ...{ p: U } }; +(o4: { [string]: T, p?: T | U }); // ok + +declare var o5: { ...{| p: T |}, ...{ [string]: U } }; +(o5: { [string]: U, p: T | U }); // ok + +declare var o6: { ...{| [string]: T |}, ...{ [string]: U } }; +(o6: { [string]: T | U }); // ok + +declare var o7: { ...{ [string]: T }, ...{| p: U |} }; +(o7: { [string]: T, p: U }); // ok + +declare var o8: { ...{ p: T }, ...{| [string]: U |} }; +(o8: { [string]: U, p?: T | U }); // ok + +declare var o9: { ...{ [string]: T }, ...{| [string]: U |} }; +(o9: { [string]: T | U }); // ok + +declare var o10: { ...{| [string]: T |}, ...{| p: U |} }; +(o10: {| [string]: T, p: U |}); // ok + +declare var o11: { ...{| p: T |}, ...{| [string]: U |} }; +(o11: {| [string]: U, p: T | U |}); // ok + +declare var o12: { ...{| [string]: T |}, ...{| [string]: U |} }; +(o12: {| [string]: T | U |}); // ok +" +`; + +exports[`type_instance.js 1`] = ` +"class A {+p: string|number} +class B extends A {p: number} + +type O1 = {...B}; +declare var o1: O1; +(o1: {p?:number}); // ok + +declare class C {[string]:number} +type O2 = {...C}; +declare var o2: O2; +(o2: {[string]:number}); // ok +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class A { + +p: string | number; +} +class B extends A { + p: number; +} + +type O1 = { ...B }; +declare var o1: O1; +(o1: { p?: number }); // ok + +declare class C { [string]: number } +type O2 = { ...C }; +declare var o2: O2; +(o2: { [string]: number }); // ok +" +`; + +exports[`type_intersection.js 1`] = ` +"declare class T {} +declare class U {} + +declare class A {} +declare class B extends A {} + +type O1 = {...{p:T}&{q:U}}; +declare var o1: O1; +(o1: {p?:T,q?:U}); // ok + +type O2 = {...{p:A}&{p:B}}; +declare var o2: O2; +(o2: {p?:B}); // ok +({p: new B}: O2); // ok +({p: new A}: O2); // error: A ~> B + +type O3 = {...{p:A}&{[string]:B}}; +declare var o3: O3; +(o3: {p:B,[string]:B});// ok: A&B = B +(o3.q: B); // ok + +type O4 = {...{[string]:A}&{p:B}}; +declare var o4: O4; +(o4: {p:B,[string]:A}); // ok: A&B = B + +type O5 = {...{[string]:A}&{[string]:B}}; +declare var o5: O5; +(o5: {[string]:B}); // ok: A&B = B +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +declare class T {} +declare class U {} + +declare class A {} +declare class B extends A {} + +type O1 = { ...{ p: T } & { q: U } }; +declare var o1: O1; +(o1: { p?: T, q?: U }); // ok + +type O2 = { ...{ p: A } & { p: B } }; +declare var o2: O2; +(o2: { p?: B }); // ok +({ p: new B() }: O2); // ok +({ p: new A() }: O2); // error: A ~> B + +type O3 = { ...{ p: A } & { [string]: B } }; +declare var o3: O3; +(o3: { [string]: B, p: B }); // ok: A&B = B +(o3.q: B); // ok + +type O4 = { ...{ [string]: A } & { p: B } }; +declare var o4: O4; +(o4: { [string]: A, p: B }); // ok: A&B = B + +type O5 = { ...{ [string]: A } & { [string]: B } }; +declare var o5: O5; +(o5: { [string]: B }); // ok: A&B = B +" +`; + +exports[`type_intersection_optional.js 1`] = ` +"declare class T {} +declare class U {} + +declare var o1: {...{p:T}&{p:U}}; +(o1: {p?:T&U}); // ok + +declare var o2: {...{p?:T}&{p:U}}; +(o2: {p?:T&U}); // ok + +declare var o3: {...{p:T}&{p?:U}}; +(o3: {p?:T&U}); // ok + +declare var o4: {...{p?:T}&{p?:U}}; +(o4: {p?:T&U}); // ok + +declare var o5: {...{|p:T|}&{p:U}}; +(o5: {p:T&U}); // ok + +declare var o6: {...{|p?:T|}&{p:U}}; +(o6: {p:T&U}); // ok + +declare var o7: {...{|p:T|}&{p?:U}}; +(o7: {p:T&U}); // ok + +declare var o8: {...{|p?:T|}&{p?:U}}; +(o8: {p?:T&U}); // ok + +declare var o9: {...{p:T}&{|p:U|}}; +(o9: {p:T&U}); // ok + +declare var o10: {...{p?:T}&{|p:U|}}; +(o10: {p:T&U}); // ok + +declare var o11: {...{p:T}&{|p?:U|}}; +(o11: {p:T&U}); // ok + +declare var o12: {...{p?:T}&{|p?:U|}}; +(o12: {p?:T&U}); // ok + +declare var o13: {...{|p:T|}&{|p:U|}}; +(o13: {|p:T&U|}); // ok + +declare var o14: {...{|p?:T|}&{|p:U|}}; +(o14: {|p:T&U|}); // ok + +declare var o15: {...{|p:T|}&{|p?:U|}}; +(o15: {|p:T&U|}); // ok + +declare var o16: {...{|p?:T|}&{|p?:U|}}; +(o16: {|p?:T&U|}); // ok + +declare var o17: {...{p:T}&{q:U}}; +(o17: {p?:T,q?:U}); // ok + +declare var o18: {...{p?:T}&{q:U}}; +(o18: {p?:T,q?:U}); // ok + +declare var o19: {...{p:T}&{q?:U}}; +(o19: {p?:T,q?:U}); // ok + +declare var o20: {...{p?:T}&{q?:U}}; +(o20: {p?:T,q?:U}); // ok + +declare var o21: {...{|p:T|}&{q:U}}; +(o21: {p:T,q?:U}); // ok +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +declare class T {} +declare class U {} + +declare var o1: { ...{ p: T } & { p: U } }; +(o1: { p?: T & U }); // ok + +declare var o2: { ...{ p?: T } & { p: U } }; +(o2: { p?: T & U }); // ok + +declare var o3: { ...{ p: T } & { p?: U } }; +(o3: { p?: T & U }); // ok + +declare var o4: { ...{ p?: T } & { p?: U } }; +(o4: { p?: T & U }); // ok + +declare var o5: { ...{| p: T |} & { p: U } }; +(o5: { p: T & U }); // ok + +declare var o6: { ...{| p?: T |} & { p: U } }; +(o6: { p: T & U }); // ok + +declare var o7: { ...{| p: T |} & { p?: U } }; +(o7: { p: T & U }); // ok + +declare var o8: { ...{| p?: T |} & { p?: U } }; +(o8: { p?: T & U }); // ok + +declare var o9: { ...{ p: T } & {| p: U |} }; +(o9: { p: T & U }); // ok + +declare var o10: { ...{ p?: T } & {| p: U |} }; +(o10: { p: T & U }); // ok + +declare var o11: { ...{ p: T } & {| p?: U |} }; +(o11: { p: T & U }); // ok + +declare var o12: { ...{ p?: T } & {| p?: U |} }; +(o12: { p?: T & U }); // ok + +declare var o13: { ...{| p: T |} & {| p: U |} }; +(o13: {| p: T & U |}); // ok + +declare var o14: { ...{| p?: T |} & {| p: U |} }; +(o14: {| p: T & U |}); // ok + +declare var o15: { ...{| p: T |} & {| p?: U |} }; +(o15: {| p: T & U |}); // ok + +declare var o16: { ...{| p?: T |} & {| p?: U |} }; +(o16: {| p?: T & U |}); // ok + +declare var o17: { ...{ p: T } & { q: U } }; +(o17: { p?: T, q?: U }); // ok + +declare var o18: { ...{ p?: T } & { q: U } }; +(o18: { p?: T, q?: U }); // ok + +declare var o19: { ...{ p: T } & { q?: U } }; +(o19: { p?: T, q?: U }); // ok + +declare var o20: { ...{ p?: T } & { q?: U } }; +(o20: { p?: T, q?: U }); // ok + +declare var o21: { ...{| p: T |} & { q: U } }; +(o21: { p: T, q?: U }); // ok +" +`; + +exports[`type_optional.js 1`] = ` +"declare class T {} +declare class U {} + +declare var a: {...{ p :T },...{ p :U }}; (a: { p?:T|U }); +declare var b: {...{ p?:T },...{ p :U }}; (b: { p?:T|U }); +declare var c: {...{ p :T },...{ p?:U }}; (c: { p?:T|U }); +declare var d: {...{ p?:T },...{ p?:U }}; (d: { p?:T|U }); + +declare var e: {...{|p :T|},...{ p :U }}; (e: { p :T|U }); +declare var f: {...{|p?:T|},...{ p :U }}; (f: { p?:T|U }); +declare var g: {...{|p :T|},...{ p?:U }}; (g: { p :T|U }); +declare var h: {...{|p?:T|},...{ p?:U }}; (h: { p?:T|U }); + +declare var i: {...{ p :T },...{|p :U|}}; (i: { p : U }); +declare var j: {...{ p?:T },...{|p :U|}}; (j: { p : U }); +declare var k: {...{ p :T },...{|p?:U|}}; (k: { p?:T|U }); +declare var l: {...{ p?:T },...{|p?:U|}}; (l: { p?:T|U }); + +declare var m: {...{|p :T|},...{|p :U|}}; (m: {|p : U|}); +declare var n: {...{|p?:T|},...{|p :U|}}; (n: {|p : U|}); +declare var o: {...{|p :T|},...{|p?:U|}}; (o: {|p :T|U|}); +declare var p: {...{|p?:T|},...{|p?:U|}}; (p: {|p?:T|U|}); +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +declare class T {} +declare class U {} + +declare var a: { ...{ p: T }, ...{ p: U } }; +(a: { p?: T | U }); +declare var b: { ...{ p?: T }, ...{ p: U } }; +(b: { p?: T | U }); +declare var c: { ...{ p: T }, ...{ p?: U } }; +(c: { p?: T | U }); +declare var d: { ...{ p?: T }, ...{ p?: U } }; +(d: { p?: T | U }); + +declare var e: { ...{| p: T |}, ...{ p: U } }; +(e: { p: T | U }); +declare var f: { ...{| p?: T |}, ...{ p: U } }; +(f: { p?: T | U }); +declare var g: { ...{| p: T |}, ...{ p?: U } }; +(g: { p: T | U }); +declare var h: { ...{| p?: T |}, ...{ p?: U } }; +(h: { p?: T | U }); + +declare var i: { ...{ p: T }, ...{| p: U |} }; +(i: { p: U }); +declare var j: { ...{ p?: T }, ...{| p: U |} }; +(j: { p: U }); +declare var k: { ...{ p: T }, ...{| p?: U |} }; +(k: { p?: T | U }); +declare var l: { ...{ p?: T }, ...{| p?: U |} }; +(l: { p?: T | U }); + +declare var m: { ...{| p: T |}, ...{| p: U |} }; +(m: {| p: U |}); +declare var n: { ...{| p?: T |}, ...{| p: U |} }; +(n: {| p: U |}); +declare var o: { ...{| p: T |}, ...{| p?: U |} }; +(o: {| p: T | U |}); +declare var p: { ...{| p?: T |}, ...{| p?: U |} }; +(p: {| p?: T | U |}); +" +`; + +exports[`type_union.js 1`] = ` +"declare class T {} +declare var x: T; + +declare class U {} +declare var y: U; + +type O1 = {...{p:T}|{q:U}}; +declare var o1: O1; +(o1: {p?:T}|{q?:U}); // ok +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +declare class T {} +declare var x: T; + +declare class U {} +declare var y: U; + +type O1 = { ...{ p: T } | { q: U } }; +declare var o1: O1; +(o1: { p?: T } | { q?: U }); // ok +" +`; diff --git a/tests/flow_type_spread/jsfmt.spec.js b/tests/flow/new_spread/jsfmt.spec.js similarity index 100% rename from tests/flow_type_spread/jsfmt.spec.js rename to tests/flow/new_spread/jsfmt.spec.js diff --git a/tests/flow/new_spread/type.js b/tests/flow/new_spread/type.js new file mode 100644 index 00000000..2aeee01b --- /dev/null +++ b/tests/flow/new_spread/type.js @@ -0,0 +1,91 @@ +declare class T {} +declare var x: T; + +declare class U {} +declare var y: U; + +declare var nil: {||}; + +// inexact: `p` may be non-own +type O1 = {...{p:T}}; +declare var o1: O1; +(o1: {p?:T}); // ok +(o1: {p:T}); // error: o1.p is optional +({}: O1); // ok +({p:x}: O1); // ok +({p:y}: O1); // error: y ~> T +({p:x,q:y}: O1); // ok + +// inexact: optional `p`, if own, must be `T` +type O2 = {...{p?:T}}; +declare var o2: O2; +(o2: {p?:T}); // ok +(o2: {p:T}); // error: o2.p is optional +({}: O2); // ok +({p:x}: O2); // ok +({p:y}: O2); // error: y ~> T +({p:x,q:y}: O2); // ok + +// can't make exact from inexact +type O3 = {|...{p:T}|}; // error: spread result is not exact + +// exact +type O4 = {...{|p:T|}}; +declare var o4: O4; +(o4: {p:T}); // ok +(o4: {|p:T|}); // error: not exact +({}: O4); // error: property `p` not found +({p:x}: O4); // ok +({p:y}: O4); // error: y ~> T +({p:x,q:y}: O4); // ok + +// can make exact from exact +type O5 = {|...{|p:T|}|}; +declare var o5: O5; +(o5: {p:T}); // ok +(o5: {|p:T|}); // ok +(nil: O5); // error: property `p` not found +({p:x}: O5); // ok +({p:y}: O5); // error: y ~> T +({p:x,q:y}: O5); // error: additional property `q` found + +// inexact p + exact p +type O6 = {...{p:T},...{|p:U|}}; +declare var o6: O6; +(o6: {p:U}); // ok +({}: O6); // error: property `p` not found +({p:x}: O6); // error: x ~> U +({p:y}: O6); // ok +({p:y,q:x}: O6); // ok + +// inexact p + exact p ~> exact +type O7 = {|...{p:T},...{|p:U|}|}; // error: spread result is not exact + +// exact p + inexact p +type O8 = {...{|p:T|},...{p:U}}; +declare var o8: O8; +(o8: {p:T|U}); // ok +(o8.p: T); // error: U ~> T +(o8.p: U); // error: T ~> U + +// inexact p + exact q +type O9 = {...{p:T},...{|q:U|}}; +declare var o9: O9; +(o9: {p?:T,q:U}); +(o9.p: T); // error: o9.p is optional +(o9.q: U); // ok + +// exact p + inexact q +type O10 = {...{|p:T|},...{q:U}}; +declare var o10: O10; +(o10: {p:mixed, q?: U}); // ok + +// inexact p + inexact q +type O11 = {...{p:T},...{q:U}}; +declare var o11: O11; +(o11: {p:mixed, q: mixed}); // ok + +// exact + exact +type O12 = {...{|p:T|},...{|q:U|}}; +declare var o12: O12; +(o12: {p:T,q:U}); // ok diff --git a/tests/flow/new_spread/type_any.js b/tests/flow/new_spread/type_any.js new file mode 100644 index 00000000..4ec21b72 --- /dev/null +++ b/tests/flow/new_spread/type_any.js @@ -0,0 +1,13 @@ +type O1 = {...any}; +var o1: O1 = (0: mixed); // ok +(o1: empty); // ok + +type O2 = {...Object}; +var o2: O2 = (0: mixed); // ok +(o2: empty); // ok + +declare var Base: any; +declare class Derived extends Base {} +type O3 = {...Derived}; +var o3: O3 = (0: mixed); // ok +(o3: empty) // ok diff --git a/tests/flow/new_spread/type_contra.js b/tests/flow/new_spread/type_contra.js new file mode 100644 index 00000000..b6ffd4b6 --- /dev/null +++ b/tests/flow/new_spread/type_contra.js @@ -0,0 +1,13 @@ +declare class T {}; + +type O1 = {...{-p:T}}; +declare var o1: O1; +(o1: {p?:mixed}); // ok +(o1: {p?:T}); // error: unknown ~> T +(o1.p: T); // errors: undefined ~> T, unknown ~> T + +type O2 = {...{-[string]:T}}; +declare var o2: O2; +(o2: {[string]:mixed}); // ok +(o2: {[string]:T}); // error: unknown ~> T +(o2.p: T); // errors: unknown ~> T diff --git a/tests/flow/new_spread/type_dict.js b/tests/flow/new_spread/type_dict.js new file mode 100644 index 00000000..3ecd63e8 --- /dev/null +++ b/tests/flow/new_spread/type_dict.js @@ -0,0 +1,38 @@ +declare class T {} +declare class U {} + +declare var o1: {...{[string]:T},...{p:U}}; +(o1: {p?:T|U,[string]:T}); // ok + +declare var o2: {...{p:T},...{[string]:U}}; +(o2: {p?:T|U,[string]:U}); // ok + +declare var o3: {...{[string]:T},...{[string]:U}}; +(o3: {[string]:T|U}); // ok + +declare var o4: {...{|[string]:T|},...{p:U}}; +(o4: {p?:T|U,[string]:T}); // ok + +declare var o5: {...{|p:T|},...{[string]:U}}; +(o5: {p:T|U,[string]:U}); // ok + +declare var o6: {...{|[string]:T|},...{[string]:U}}; +(o6: {[string]:T|U}); // ok + +declare var o7: {...{[string]:T},...{|p:U|}}; +(o7: {p:U,[string]:T}); // ok + +declare var o8: {...{p:T},...{|[string]:U|}}; +(o8: {p?:T|U,[string]:U}); // ok + +declare var o9: {...{[string]:T},...{|[string]:U|}}; +(o9: {[string]:T|U}); // ok + +declare var o10: {...{|[string]:T|},...{|p:U|}}; +(o10: {|p:U,[string]:T|}); // ok + +declare var o11: {...{|p :T|},...{|[string]:U|}}; +(o11: {|p:T|U,[string]:U|}); // ok + +declare var o12: {...{|[string]:T|},...{|[string]:U|}}; +(o12: {|[string]:T|U|}); // ok diff --git a/tests/flow/new_spread/type_instance.js b/tests/flow/new_spread/type_instance.js new file mode 100644 index 00000000..dd8d4f37 --- /dev/null +++ b/tests/flow/new_spread/type_instance.js @@ -0,0 +1,11 @@ +class A {+p: string|number} +class B extends A {p: number} + +type O1 = {...B}; +declare var o1: O1; +(o1: {p?:number}); // ok + +declare class C {[string]:number} +type O2 = {...C}; +declare var o2: O2; +(o2: {[string]:number}); // ok diff --git a/tests/flow/new_spread/type_intersection.js b/tests/flow/new_spread/type_intersection.js new file mode 100644 index 00000000..1895418e --- /dev/null +++ b/tests/flow/new_spread/type_intersection.js @@ -0,0 +1,28 @@ +declare class T {} +declare class U {} + +declare class A {} +declare class B extends A {} + +type O1 = {...{p:T}&{q:U}}; +declare var o1: O1; +(o1: {p?:T,q?:U}); // ok + +type O2 = {...{p:A}&{p:B}}; +declare var o2: O2; +(o2: {p?:B}); // ok +({p: new B}: O2); // ok +({p: new A}: O2); // error: A ~> B + +type O3 = {...{p:A}&{[string]:B}}; +declare var o3: O3; +(o3: {p:B,[string]:B});// ok: A&B = B +(o3.q: B); // ok + +type O4 = {...{[string]:A}&{p:B}}; +declare var o4: O4; +(o4: {p:B,[string]:A}); // ok: A&B = B + +type O5 = {...{[string]:A}&{[string]:B}}; +declare var o5: O5; +(o5: {[string]:B}); // ok: A&B = B diff --git a/tests/flow/new_spread/type_intersection_optional.js b/tests/flow/new_spread/type_intersection_optional.js new file mode 100644 index 00000000..1e109203 --- /dev/null +++ b/tests/flow/new_spread/type_intersection_optional.js @@ -0,0 +1,65 @@ +declare class T {} +declare class U {} + +declare var o1: {...{p:T}&{p:U}}; +(o1: {p?:T&U}); // ok + +declare var o2: {...{p?:T}&{p:U}}; +(o2: {p?:T&U}); // ok + +declare var o3: {...{p:T}&{p?:U}}; +(o3: {p?:T&U}); // ok + +declare var o4: {...{p?:T}&{p?:U}}; +(o4: {p?:T&U}); // ok + +declare var o5: {...{|p:T|}&{p:U}}; +(o5: {p:T&U}); // ok + +declare var o6: {...{|p?:T|}&{p:U}}; +(o6: {p:T&U}); // ok + +declare var o7: {...{|p:T|}&{p?:U}}; +(o7: {p:T&U}); // ok + +declare var o8: {...{|p?:T|}&{p?:U}}; +(o8: {p?:T&U}); // ok + +declare var o9: {...{p:T}&{|p:U|}}; +(o9: {p:T&U}); // ok + +declare var o10: {...{p?:T}&{|p:U|}}; +(o10: {p:T&U}); // ok + +declare var o11: {...{p:T}&{|p?:U|}}; +(o11: {p:T&U}); // ok + +declare var o12: {...{p?:T}&{|p?:U|}}; +(o12: {p?:T&U}); // ok + +declare var o13: {...{|p:T|}&{|p:U|}}; +(o13: {|p:T&U|}); // ok + +declare var o14: {...{|p?:T|}&{|p:U|}}; +(o14: {|p:T&U|}); // ok + +declare var o15: {...{|p:T|}&{|p?:U|}}; +(o15: {|p:T&U|}); // ok + +declare var o16: {...{|p?:T|}&{|p?:U|}}; +(o16: {|p?:T&U|}); // ok + +declare var o17: {...{p:T}&{q:U}}; +(o17: {p?:T,q?:U}); // ok + +declare var o18: {...{p?:T}&{q:U}}; +(o18: {p?:T,q?:U}); // ok + +declare var o19: {...{p:T}&{q?:U}}; +(o19: {p?:T,q?:U}); // ok + +declare var o20: {...{p?:T}&{q?:U}}; +(o20: {p?:T,q?:U}); // ok + +declare var o21: {...{|p:T|}&{q:U}}; +(o21: {p:T,q?:U}); // ok diff --git a/tests/flow/new_spread/type_optional.js b/tests/flow/new_spread/type_optional.js new file mode 100644 index 00000000..5fa828e3 --- /dev/null +++ b/tests/flow/new_spread/type_optional.js @@ -0,0 +1,22 @@ +declare class T {} +declare class U {} + +declare var a: {...{ p :T },...{ p :U }}; (a: { p?:T|U }); +declare var b: {...{ p?:T },...{ p :U }}; (b: { p?:T|U }); +declare var c: {...{ p :T },...{ p?:U }}; (c: { p?:T|U }); +declare var d: {...{ p?:T },...{ p?:U }}; (d: { p?:T|U }); + +declare var e: {...{|p :T|},...{ p :U }}; (e: { p :T|U }); +declare var f: {...{|p?:T|},...{ p :U }}; (f: { p?:T|U }); +declare var g: {...{|p :T|},...{ p?:U }}; (g: { p :T|U }); +declare var h: {...{|p?:T|},...{ p?:U }}; (h: { p?:T|U }); + +declare var i: {...{ p :T },...{|p :U|}}; (i: { p : U }); +declare var j: {...{ p?:T },...{|p :U|}}; (j: { p : U }); +declare var k: {...{ p :T },...{|p?:U|}}; (k: { p?:T|U }); +declare var l: {...{ p?:T },...{|p?:U|}}; (l: { p?:T|U }); + +declare var m: {...{|p :T|},...{|p :U|}}; (m: {|p : U|}); +declare var n: {...{|p?:T|},...{|p :U|}}; (n: {|p : U|}); +declare var o: {...{|p :T|},...{|p?:U|}}; (o: {|p :T|U|}); +declare var p: {...{|p?:T|},...{|p?:U|}}; (p: {|p?:T|U|}); diff --git a/tests/flow/new_spread/type_union.js b/tests/flow/new_spread/type_union.js new file mode 100644 index 00000000..21a8619e --- /dev/null +++ b/tests/flow/new_spread/type_union.js @@ -0,0 +1,9 @@ +declare class T {} +declare var x: T; + +declare class U {} +declare var y: U; + +type O1 = {...{p:T}|{q:U}}; +declare var o1: O1; +(o1: {p?:T}|{q?:U}); // ok diff --git a/tests/flow_type_spread/__snapshots__/jsfmt.spec.js.snap b/tests/flow_type_spread/__snapshots__/jsfmt.spec.js.snap deleted file mode 100644 index 27cbda90..00000000 --- a/tests/flow_type_spread/__snapshots__/jsfmt.spec.js.snap +++ /dev/null @@ -1,8 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`spread.js 1`] = ` -"type TypeB = { ...TypeA }; -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -type TypeB = { ...TypeA }; -" -`; diff --git a/tests/flow_type_spread/spread.js b/tests/flow_type_spread/spread.js deleted file mode 100644 index dd188e7d..00000000 --- a/tests/flow_type_spread/spread.js +++ /dev/null @@ -1 +0,0 @@ -type TypeB = { ...TypeA };