Preserve empty line after comment (#493)
The logic was already working, it was just special-cased to the first comment of the file! Presumably because the new line detection logic used to be broken ;) I manually checked the first 10 snapshots and they are all legit, so I assume that all of them are. Fixes #356master
parent
8f26568bc8
commit
956779ec17
|
@ -372,7 +372,6 @@ function printComments(path, print, options) {
|
|||
var parent = path.getParentNode();
|
||||
var printed = print(path);
|
||||
var comments = n.Node.check(value) && types.getFieldValue(value, "comments");
|
||||
var isFirstInProgram = n.Program.check(parent) && parent.body[0] === value;
|
||||
|
||||
if (!comments || comments.length === 0) {
|
||||
return printed;
|
||||
|
@ -392,14 +391,8 @@ function printComments(path, print, options) {
|
|||
) {
|
||||
leadingParts.push(printLeadingComment(commentPath, print, options));
|
||||
|
||||
// Support a special case where a comment exists at the very top
|
||||
// of the file. Allow the user to add spacing between that file
|
||||
// and any code beneath it.
|
||||
const text = options.originalText;
|
||||
if (
|
||||
isFirstInProgram &&
|
||||
util.hasNewline(text, util.skipNewline(text, util.locEnd(comment)))
|
||||
) {
|
||||
if (util.hasNewline(text, util.skipNewline(text, util.locEnd(comment)))) {
|
||||
leadingParts.push(hardline);
|
||||
}
|
||||
} else if (trailing) {
|
||||
|
|
|
@ -27,6 +27,7 @@ import a from \"a\";
|
|||
a();
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
/* @flow */
|
||||
|
||||
\"use strict\";
|
||||
|
||||
import a from \"a\";
|
||||
|
|
|
@ -107,6 +107,7 @@ function param_anno2(
|
|||
// error below, since we\'re assigning elements to batchRequests
|
||||
// which lack a path property.
|
||||
// just assign result to new var instead of reassigning to param.
|
||||
|
||||
// Transform the requests to the format the Graph API expects.
|
||||
batchRequests = batchRequests.map(request => {
|
||||
return {
|
||||
|
@ -149,6 +150,7 @@ function foo() {
|
|||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
let myClassInstance: MyClass = null;
|
||||
// forward ref ok, null ~> class error
|
||||
|
||||
function bar(): MyClass {
|
||||
return null; // forward ref ok, null ~> class error
|
||||
}
|
||||
|
|
|
@ -107,6 +107,7 @@ function reduce_test() {
|
|||
});
|
||||
|
||||
/* Added later, because the above is insufficient */
|
||||
|
||||
// acc is element type of array when no init is provided
|
||||
[\"\"].reduce((acc, str) => acc * str.length); // error, string ~> number
|
||||
[\"\"].reduceRight((acc, str) => acc * str.length); // error, string ~> number
|
||||
|
|
|
@ -68,6 +68,7 @@ async function f1(): Promise<boolean> {
|
|||
|
||||
// await: (p: Promise<T> | T) => T
|
||||
//
|
||||
|
||||
async function f2(p: Promise<number>): Promise<number> {
|
||||
var x: number = await p;
|
||||
var y: number = await 1;
|
||||
|
@ -86,10 +87,12 @@ async function f4(p: Promise<number>): Promise<boolean> {
|
|||
|
||||
// async arrow functions
|
||||
//
|
||||
|
||||
var f5: () => Promise<number> = async () => await 1;
|
||||
|
||||
// async methods
|
||||
//
|
||||
|
||||
class C {
|
||||
async m() {
|
||||
return 1;
|
||||
|
@ -106,6 +109,7 @@ class C {
|
|||
}
|
||||
|
||||
// async function props
|
||||
|
||||
var obj = { f: async () => await 1 };
|
||||
var objf: () => Promise<number> = obj.f;
|
||||
"
|
||||
|
@ -322,9 +326,11 @@ function test1() {
|
|||
//
|
||||
// void returns:
|
||||
//
|
||||
|
||||
// inference should produce return type Promise<void>
|
||||
// in the absence of an explicit return
|
||||
//
|
||||
|
||||
function test2() {
|
||||
async function voidoid1() {
|
||||
console.log(\"HEY\");
|
||||
|
@ -336,6 +342,7 @@ function test2() {
|
|||
|
||||
// annotated return type of Promise<void> should work
|
||||
//
|
||||
|
||||
function test3() {
|
||||
async function voidoid4(): Promise<void> { // ok
|
||||
console.log(\"HEY\");
|
||||
|
@ -346,6 +353,7 @@ function test3() {
|
|||
// (note: misannotated return types with explicit
|
||||
// return statements are covered in async.js)
|
||||
//
|
||||
|
||||
function test4() {
|
||||
async function voidoid5(): void { // error, void != Promise<void>
|
||||
console.log(\"HEY\");
|
||||
|
|
|
@ -44,6 +44,7 @@ x ^= 0;
|
|||
x &= 0;
|
||||
|
||||
// regression tests -- OK to assign consts like this:
|
||||
|
||||
const { foo } = { foo: \"foo\" };
|
||||
const [bar] = [\"bar\"];
|
||||
(foo: number); // error: string ~> number
|
||||
|
@ -298,6 +299,7 @@ function type_reassign() {
|
|||
}
|
||||
|
||||
// class x *
|
||||
|
||||
function class_type() {
|
||||
class A {}
|
||||
type A = number; // error: name already bound
|
||||
|
@ -324,6 +326,7 @@ function class_var() {
|
|||
}
|
||||
|
||||
// let x *
|
||||
|
||||
function let_type() {
|
||||
let A = 0;
|
||||
type A = number; // error: name already bound
|
||||
|
@ -350,6 +353,7 @@ function let_var() {
|
|||
}
|
||||
|
||||
// const x *
|
||||
|
||||
function const_type() {
|
||||
const A = 0;
|
||||
type A = number; // error: name already bound
|
||||
|
@ -381,6 +385,7 @@ function const_reassign() {
|
|||
}
|
||||
|
||||
// var x *
|
||||
|
||||
function var_type() {
|
||||
var A = 0;
|
||||
type A = number; // error: name already bound
|
||||
|
@ -407,6 +412,7 @@ function var_var() {
|
|||
}
|
||||
|
||||
// function x *
|
||||
|
||||
function function_toplevel() {
|
||||
function a() {}
|
||||
function a() {}
|
||||
|
@ -420,6 +426,7 @@ function function_block() {
|
|||
}
|
||||
|
||||
// corner cases
|
||||
|
||||
function var_shadow_nested_scope() {
|
||||
{
|
||||
let x = 0;
|
||||
|
@ -439,6 +446,7 @@ function type_shadow_nested_scope() {
|
|||
}
|
||||
|
||||
// fn params name clash
|
||||
|
||||
function fn_params_name_clash(x, x /* error: x already bound */) {}
|
||||
function fn_params_clash_fn_binding(x, y) {
|
||||
let x = 0; // error: x already bound
|
||||
|
@ -788,6 +796,7 @@ type T1 = T2; // ok
|
|||
type T2 = number;
|
||||
|
||||
// --- lets ---
|
||||
|
||||
// to be correct, we would
|
||||
// - not allow forward refs to lets from value positions,
|
||||
// while let is in TDZ.
|
||||
|
@ -799,6 +808,7 @@ type T2 = number;
|
|||
// a lambda runs. But a simple conservative approach would prohibit
|
||||
// forward references to let/consts from within lambdas entirely,
|
||||
// which would be annoying. TODO
|
||||
|
||||
function f0() {
|
||||
var v = x * c; // errors, let + const referenced before decl
|
||||
let x = 0;
|
||||
|
@ -860,15 +870,18 @@ function f5() {
|
|||
// value (i.e., class or function). this is a basic flaw in our
|
||||
// phasing of AST traversal, and will be fixed.
|
||||
//
|
||||
|
||||
var x: C; // ok
|
||||
var y = new C(); // error: let ref before decl from value position
|
||||
class C {}
|
||||
|
||||
var z: C = new C(); // ok
|
||||
// --- vars ---
|
||||
|
||||
// it\'s possible to annotate a var with a non-maybe type,
|
||||
// but leave it uninitialized until later (as long as it\'s
|
||||
// initialized before use)
|
||||
|
||||
var a: number; // not an error per se - only if used before init
|
||||
function f(n: number) {
|
||||
return n;
|
||||
|
|
|
@ -183,6 +183,7 @@ var bar1: Bar = new Bar(); // OK
|
|||
var bar2: Bar = Bar.factory(); // OK
|
||||
// NB: Don\'t write expected errors using Foo to avoid error collapse hiding an
|
||||
// unexpected failure in the above code.
|
||||
|
||||
var B = class Baz {};
|
||||
var b = new Baz(); // error: Baz is not a runtime binding in this scope
|
||||
var C = class Qux {};
|
||||
|
|
|
@ -89,6 +89,7 @@ function takes_string(_: string) {}
|
|||
|
||||
// global write from function
|
||||
//
|
||||
|
||||
var global_x = \"hello\";
|
||||
|
||||
function global_f() {}
|
||||
|
@ -103,6 +104,7 @@ takes_string(global_x); // error
|
|||
global_x = 42; // shouldn\'t pollute linear refinement
|
||||
// local write from function
|
||||
//
|
||||
|
||||
function local_func() {
|
||||
var local_x = \"hello\";
|
||||
|
||||
|
@ -120,6 +122,7 @@ function local_func() {
|
|||
|
||||
// global write from method
|
||||
//
|
||||
|
||||
var global_y = \"hello\";
|
||||
|
||||
var global_o = {
|
||||
|
@ -136,6 +139,7 @@ takes_string(global_y); // error
|
|||
global_y = 42; // shouldn\'t pollute linear refinement
|
||||
// local write from method
|
||||
//
|
||||
|
||||
function local_meth() {
|
||||
var local_y = \"hello\";
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ declare module foo {
|
|||
// This file triggers a violation of the \"disjoint-or-nested ranges invariant\"
|
||||
// that we implicitly assume in type-at-pos and coverage implementations. In
|
||||
// particular, when unchecked it causes a crash with coverage --color.
|
||||
|
||||
declare module bar {
|
||||
}
|
||||
"
|
||||
|
@ -65,9 +66,11 @@ declare module foo {
|
|||
// This file triggers a violation of the \"disjoint-or-nested ranges invariant\"
|
||||
// that we implicitly assume in type-at-pos and coverage implementations. In
|
||||
// particular, when unchecked it causes non-termination with coverage --color.
|
||||
|
||||
declare module bar {
|
||||
}
|
||||
// TODO
|
||||
|
||||
declare class qux {}
|
||||
"
|
||||
`;
|
||||
|
|
|
@ -23,6 +23,7 @@ module.exports = B;
|
|||
var A = require(\"./A\");
|
||||
|
||||
//class B extends A { }
|
||||
|
||||
module.exports = B;
|
||||
"
|
||||
`;
|
||||
|
|
|
@ -900,6 +900,7 @@ import DefaultD from \"./D\"; // Error: No such module
|
|||
// ================================================ //
|
||||
// == CommonJS Clobbering Literal Exports -> ES6 == //
|
||||
// ================================================ //
|
||||
|
||||
import { doesntExist1 } from \"CommonJS_Clobbering_Lit\"; // Error: Not an exported binding
|
||||
import { numberValue1 } from \"CommonJS_Clobbering_Lit\";
|
||||
var c1: number = numberValue1;
|
||||
|
@ -920,6 +921,7 @@ var f4: string = CJS_Clobb_Lit_NS.default.numberValue5; // Error: number ~> stri
|
|||
// ============================================== //
|
||||
// == CommonJS Clobbering Class Exports -> ES6 == //
|
||||
// ============================================== //
|
||||
|
||||
import { doesntExist2 } from \"CommonJS_Clobbering_Class\"; // Error: Not an exported binding
|
||||
// The following import should error because class statics are not turned into
|
||||
// named exports for now. This avoids complexities with polymorphic static
|
||||
|
@ -941,6 +943,7 @@ var i3: string = new CJS_Clobb_Class_NS.default().instNumber2(); // Error: numbe
|
|||
// =================================== //
|
||||
// == CommonJS Named Exports -> ES6 == //
|
||||
// =================================== //
|
||||
|
||||
import { doesntExist3 } from \"CommonJS_Named\"; // Error: Not an exported binding
|
||||
import { numberValue2 } from \"CommonJS_Named\";
|
||||
var j1: number = numberValue2;
|
||||
|
@ -959,6 +962,7 @@ var m3: string = CJS_Named_NS.numberValue4; // Error: number ~> string
|
|||
//////////////////////////////
|
||||
// == ES6 Default -> ES6 == //
|
||||
//////////////////////////////
|
||||
|
||||
import { doesntExist4 } from \"ES6_Default_AnonFunction1\"; // Error: Not an exported binding
|
||||
import ES6_Def_AnonFunc1 from \"ES6_Default_AnonFunction1\";
|
||||
var n1: number = ES6_Def_AnonFunc1();
|
||||
|
@ -972,6 +976,7 @@ var q2: string = new ES6_Def_NamedClass1().givesANum(); // Error: number ~> stri
|
|||
////////////////////////////
|
||||
// == ES6 Named -> ES6 == //
|
||||
////////////////////////////
|
||||
|
||||
import doesntExist5 from \"ES6_Named1\"; // Error: Not an exported binding
|
||||
import { specifierNumber1 as specifierNumber1_1 } from \"ES6_Named1\";
|
||||
var r1: number = specifierNumber1_1;
|
||||
|
@ -1010,6 +1015,7 @@ var ac2: string = numberValue5; // Error: number ~> string
|
|||
///////////////////////////////////
|
||||
// == ES6 Default -> CommonJS == //
|
||||
///////////////////////////////////
|
||||
|
||||
require(\"ES6_Default_AnonFunction2\").doesntExist; // Error: \'doesntExist\' isn\'t an export
|
||||
var ES6_Def_AnonFunc2 = require(\"ES6_Default_AnonFunction2\").default;
|
||||
var ad1: number = ES6_Def_AnonFunc2();
|
||||
|
@ -1023,6 +1029,7 @@ var ag2: string = new ES6_Def_NamedClass2().givesANum(); // Error: number ~> str
|
|||
/////////////////////////////////
|
||||
// == ES6 Named -> CommonJS == //
|
||||
/////////////////////////////////
|
||||
|
||||
var specifierNumber4 = require(\"ES6_Named2\").specifierNumber4;
|
||||
var ah1: number = specifierNumber4;
|
||||
var ah2: string = specifierNumber4; // Error: number ~> string
|
||||
|
@ -1061,6 +1068,7 @@ var ar2: string = numberValue7; // Error: number ~> string
|
|||
////////////////////////////////////////////////////////
|
||||
// == ES6 Default+Named -> ES6 import Default+Named== //
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
import defaultNum, { str as namedStr } from \"./ES6_DefaultAndNamed\";
|
||||
|
||||
var as1: number = defaultNum;
|
||||
|
@ -1070,6 +1078,7 @@ var as4: number = namedStr; // Error: string ~> number
|
|||
////////////////////////////////////////
|
||||
// == Side-effect only ES6 imports == //
|
||||
////////////////////////////////////////
|
||||
|
||||
import \"./SideEffects\";
|
||||
|
||||
//////////////////////////////////////////////
|
||||
|
|
|
@ -40,6 +40,7 @@ import type { str2 } from \"declare_m_e_with_other_type_declares\";
|
|||
* \`declare var exports\` is deprecated, so we have a grace period where both
|
||||
* syntaxes will work.
|
||||
*/
|
||||
|
||||
import DEPRECATED__declare_var_exports from \"DEPRECATED__declare_var_exports\";
|
||||
(DEPRECATED__declare_var_exports: number);
|
||||
(DEPRECATED__declare_var_exports: string); // Error: number ~> string
|
||||
|
|
|
@ -45,6 +45,7 @@ declare module \"declare_m_e_with_other_type_declares\" {
|
|||
* \`declare var exports\` is deprecated, so we have a grace period where both
|
||||
* syntaxes will work.
|
||||
*/
|
||||
|
||||
declare module \"DEPRECATED__declare_var_exports\" {
|
||||
declare var exports: number;
|
||||
/**
|
||||
|
|
|
@ -47,6 +47,7 @@ var k4: toz = foo(k1); // works
|
|||
//////////////////////////////////////////////////////////
|
||||
// == Declared Module with exports prop (issue 880) == //
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
import blah from \"foo\";
|
||||
import type { Foo, Bar, Id } from \"foo\";
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ function f(x) {
|
|||
|
||||
var x = null;
|
||||
//...
|
||||
|
||||
f(x);
|
||||
"
|
||||
`;
|
||||
|
|
|
@ -505,6 +505,7 @@ foo = (i: number) => {
|
|||
};
|
||||
|
||||
// Also make sure that the following doesn\'t loop
|
||||
|
||||
declare var o;
|
||||
var { x: o } = o;
|
||||
"
|
||||
|
|
|
@ -75,6 +75,7 @@ exports[`test use_strict_with_flow.js 1`] = `
|
|||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
\"use strict\";
|
||||
/* @flow */
|
||||
|
||||
(\"\": void); // error
|
||||
"
|
||||
`;
|
||||
|
|
|
@ -1003,6 +1003,7 @@ import DefaultD from \"./D\"; // Error: No such module
|
|||
// ================================================ //
|
||||
// == CommonJS Clobbering Literal Exports -> ES6 == //
|
||||
// ================================================ //
|
||||
|
||||
import { doesntExist1 } from \"CommonJS_Clobbering_Lit\"; // Error: Not an exported binding
|
||||
import { numberValue1 } from \"CommonJS_Clobbering_Lit\";
|
||||
var c1: number = numberValue1;
|
||||
|
@ -1023,6 +1024,7 @@ var f4: string = CJS_Clobb_Lit_NS.default.numberValue5; // Error: number ~> stri
|
|||
// ============================================== //
|
||||
// == CommonJS Clobbering Class Exports -> ES6 == //
|
||||
// ============================================== //
|
||||
|
||||
import { doesntExist2 } from \"CommonJS_Clobbering_Class\"; // Error: Not an exported binding
|
||||
// The following import should error because class statics are not turned into
|
||||
// named exports for now. This avoids complexities with polymorphic static
|
||||
|
@ -1044,6 +1046,7 @@ var i3: string = new CJS_Clobb_Class_NS.default().instNumber2(); // Error: numbe
|
|||
// =================================== //
|
||||
// == CommonJS Named Exports -> ES6 == //
|
||||
// =================================== //
|
||||
|
||||
import { doesntExist3 } from \"CommonJS_Named\"; // Error: Not an exported binding
|
||||
import { numberValue2 } from \"CommonJS_Named\";
|
||||
var j1: number = numberValue2;
|
||||
|
@ -1062,6 +1065,7 @@ var m3: string = CJS_Named_NS.numberValue4; // Error: number ~> string
|
|||
//////////////////////////////
|
||||
// == ES6 Default -> ES6 == //
|
||||
//////////////////////////////
|
||||
|
||||
import { doesntExist4 } from \"ES6_Default_AnonFunction1\"; // Error: Not an exported binding
|
||||
import ES6_Def_AnonFunc1 from \"ES6_Default_AnonFunction1\";
|
||||
var n1: number = ES6_Def_AnonFunc1();
|
||||
|
@ -1078,6 +1082,7 @@ var q2: string = new ES6_Def_NamedClass1().givesANum(); // Error: number ~> stri
|
|||
////////////////////////////
|
||||
// == ES6 Named -> ES6 == //
|
||||
////////////////////////////
|
||||
|
||||
import doesntExist5 from \"ES6_Named1\"; // Error: Not an exported binding
|
||||
import { specifierNumber1 as specifierNumber1_1 } from \"ES6_Named1\";
|
||||
var r1: number = specifierNumber1_1;
|
||||
|
@ -1122,6 +1127,7 @@ var ac2: string = numberValue5; // Error: number ~> string
|
|||
///////////////////////////////////
|
||||
// == ES6 Default -> CommonJS == //
|
||||
///////////////////////////////////
|
||||
|
||||
require(\"ES6_Default_AnonFunction2\").doesntExist; // Error: \'doesntExist\' isn\'t an export
|
||||
var ES6_Def_AnonFunc2 = require(\"ES6_Default_AnonFunction2\").default;
|
||||
var ad1: number = ES6_Def_AnonFunc2();
|
||||
|
@ -1138,6 +1144,7 @@ var ag2: string = new ES6_Def_NamedClass2().givesANum(); // Error: number ~> str
|
|||
/////////////////////////////////
|
||||
// == ES6 Named -> CommonJS == //
|
||||
/////////////////////////////////
|
||||
|
||||
var specifierNumber4 = require(\"ES6_Named2\").specifierNumber4;
|
||||
var ah1: number = specifierNumber4;
|
||||
var ah2: string = specifierNumber4; // Error: number ~> string
|
||||
|
@ -1182,6 +1189,7 @@ var ar2: string = numberValue7; // Error: number ~> string
|
|||
////////////////////////////////////////////////////////
|
||||
// == ES6 Default+Named -> ES6 import Default+Named== //
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
import defaultNum, { str as namedStr } from \"./ES6_DefaultAndNamed\";
|
||||
|
||||
var as1: number = defaultNum;
|
||||
|
@ -1191,6 +1199,7 @@ var as4: number = namedStr; // Error: string ~> number
|
|||
////////////////////////////////////////
|
||||
// == Side-effect only ES6 imports == //
|
||||
////////////////////////////////////////
|
||||
|
||||
import \"./SideEffects\";
|
||||
|
||||
//////////////////////////////////////////////
|
||||
|
@ -1298,6 +1307,7 @@ CommonJS_Clobbering_Frozen.numberValue1 = 123; // Error: exports are frozen
|
|||
//
|
||||
// Requires
|
||||
//
|
||||
|
||||
function testRequires() {
|
||||
// CommonJS module
|
||||
var DefaultA = require(\"A\");
|
||||
|
|
|
@ -275,6 +275,7 @@ new ClassFoo1(); // Error: ClassFoo1 is not a value-identifier
|
|||
///////////////////////////////////////////////
|
||||
// == Importing Class Type (Named Export) == //
|
||||
///////////////////////////////////////////////
|
||||
|
||||
import type { ClassFoo2 } from \"./ExportNamed_Class\";
|
||||
import { foo2Inst } from \"./ExportNamed_Class\";
|
||||
|
||||
|
@ -284,6 +285,7 @@ new ClassFoo2(); // Error: ClassFoo2 is not a value-identifier
|
|||
/////////////////////////////////////////////////////
|
||||
// == Importing Class Type (CJS Default Export) == //
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
import type ClassFoo3T from \"./ExportCJSDefault_Class\";
|
||||
import ClassFoo3 from \"./ExportCJSDefault_Class\";
|
||||
var c1: ClassFoo3T = new ClassFoo3();
|
||||
|
@ -291,6 +293,7 @@ new ClassFoo3T(); // Error: ClassFoo3 is not a value-identifier
|
|||
///////////////////////////////////////////////////
|
||||
// == Importing Class Type (CJS Named Export) == //
|
||||
///////////////////////////////////////////////////
|
||||
|
||||
import type { ClassFoo4, ClassFoo5 } from \"./ExportCJSNamed_Class\";
|
||||
import { foo4Inst, foo5Inst } from \"./ExportCJSNamed_Class\";
|
||||
|
||||
|
@ -302,6 +305,7 @@ var d3: typeof ClassFoo5 = foo5Inst; // Error: Can\'t typeof a type alias
|
|||
////////////////////////////////////////////
|
||||
// == Import Type Alias (Named Export) == //
|
||||
////////////////////////////////////////////
|
||||
|
||||
import type { AliasFoo3 } from \"./ExportNamed_Alias\";
|
||||
import { givesAFoo3Obj } from \"./ExportNamed_Alias\";
|
||||
var e1: AliasFoo3 = givesAFoo3Obj();
|
||||
|
@ -310,18 +314,22 @@ var e3: typeof AliasFoo3 = givesAFoo3Obj(); // Error: Can\'t typeof a type alias
|
|||
//////////////////////////////////////////////
|
||||
// == Import Type Alias (Default Export) == //
|
||||
//////////////////////////////////////////////
|
||||
|
||||
// TODO: No support for this right now. It\'s most likely possible, but it\'s
|
||||
// unclear how useful it is at the moment and it entails a little
|
||||
// more work than named type exports, so I\'m punting on it for now.
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
// == Import Type With Non-Alias Compatible Value == //
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
import type { numValue } from \"./ExportsANumber\"; // Error: Cannot import-type a number value
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// == Regression Test: https://github.com/facebook/flow/issues/359 == //
|
||||
// Ensure that type bindings stay type bindings across function body //
|
||||
// env contexts. //
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
import type ClassFoo6 from \"./issue-359\";
|
||||
function foo() {
|
||||
ClassFoo6; // Error: Not a value binding
|
||||
|
|
|
@ -306,6 +306,7 @@ new ClassFoo1T(); // Error: ClassFoo1T is not bound to a value
|
|||
/////////////////////////////////////////////////
|
||||
// == Importing Class Typeof (Named Export) == //
|
||||
/////////////////////////////////////////////////
|
||||
|
||||
import typeof { ClassFoo2 as ClassFoo2T } from \"./ExportNamed_Class\";
|
||||
import { ClassFoo2 } from \"./ExportNamed_Class\";
|
||||
|
||||
|
@ -315,6 +316,7 @@ new ClassFoo2T(); // Error: ClassFoo2T is not bound to a value
|
|||
///////////////////////////////////////////////////////
|
||||
// == Importing Class Typeof (CJS Default Export) == //
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
import typeof ClassFoo3T from \"./ExportCJSDefault_Class\";
|
||||
import ClassFoo3 from \"./ExportCJSDefault_Class\";
|
||||
|
||||
|
@ -323,6 +325,7 @@ var c2: ClassFoo3T = new ClassFoo3(); // Error: ClassFoo3 (inst) ~> ClassFoo3 (c
|
|||
/////////////////////////////////////////////////////
|
||||
// == Importing Class Typeof (CJS Named Export) == //
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
import typeof { ClassFoo4 as ClassFoo4T } from \"./ExportCJSNamed_Class\";
|
||||
import { ClassFoo4 } from \"./ExportCJSNamed_Class\";
|
||||
|
||||
|
@ -331,16 +334,20 @@ var d2: ClassFoo4T = new ClassFoo4(); // Error: ClassFoo4 (inst) ~> ClassFoo4 (c
|
|||
//////////////////////////////////////////////
|
||||
// == Import Typeof Alias (Named Export) == //
|
||||
//////////////////////////////////////////////
|
||||
|
||||
import typeof { AliasFoo3 } from \"./ExportNamed_Alias\"; // Error: Can\'t \`import typeof\` type aliases!
|
||||
////////////////////////////////////////////////
|
||||
// == Import Typeof Alias (Default Export) == //
|
||||
////////////////////////////////////////////////
|
||||
|
||||
// TODO: No support for this right now. It\'s most likely possible, but it\'s
|
||||
// unclear how useful it is at the moment and it entails a little
|
||||
// more work than named type exports, so I\'m punting on it for now.
|
||||
|
||||
///////////////////////////////////////////////////////////////
|
||||
// == Import Typeof With Non-Class Value (Default Export) == //
|
||||
///////////////////////////////////////////////////////////////
|
||||
|
||||
import typeof num_default from \"./ExportDefault_Number\";
|
||||
|
||||
var f1: num_default = 42;
|
||||
|
@ -348,6 +355,7 @@ var f2: num_default = \"asdf\"; // Error: string ~> number
|
|||
/////////////////////////////////////////////////////////////
|
||||
// == Import Typeof With Non-Class Value (Named Export) == //
|
||||
/////////////////////////////////////////////////////////////
|
||||
|
||||
import typeof { num as num_named } from \"./ExportNamed_Number\";
|
||||
|
||||
var g1: num_named = 42;
|
||||
|
@ -355,6 +363,7 @@ var g2: num_named = \"asdf\"; // Error: string ~> number
|
|||
///////////////////////////////////////////////////////////////////
|
||||
// == Import Typeof With Non-Class Value (CJS Default Export) == //
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
import typeof num_cjs_default from \"./ExportCJSDefault_Number\";
|
||||
|
||||
var h1: num_cjs_default = 42;
|
||||
|
@ -362,6 +371,7 @@ var h2: num_cjs_default = \"asdf\"; // Error: string ~> number
|
|||
/////////////////////////////////////////////////////////////////
|
||||
// == Import Typeof With Non-Class Value (CJS Named Export) == //
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
import typeof { num as num_cjs_named } from \"./ExportCJSNamed_Number\";
|
||||
|
||||
var i1: num_cjs_named = 42;
|
||||
|
@ -369,6 +379,7 @@ var i2: num_cjs_named = \"asdf\"; // Error: string ~> number
|
|||
///////////////////////////////////////////////
|
||||
// == Import Typeof ModuleNamespaceObject == //
|
||||
///////////////////////////////////////////////
|
||||
|
||||
import typeof * as ModuleNSObjT from \"./ExportNamed_Multi\";
|
||||
var j1: ModuleNSObjT = { num: 42, str: \"asdf\" };
|
||||
var j2: ModuleNSObjT = { num: 42, str: 42 }; // Error: number ~> string
|
||||
|
|
|
@ -8,6 +8,7 @@ export type B = string;
|
|||
// @flow
|
||||
var A = require(\"./A\");
|
||||
//import type C from \'./C\';
|
||||
|
||||
export type B = string;
|
||||
"
|
||||
`;
|
||||
|
|
|
@ -94,6 +94,7 @@ var k: K = { x: \"\", y: \"\" }; // error: x should be number
|
|||
declare class C { x: number }
|
||||
declare class D extends C, Other {} // error: multiple extends
|
||||
//declare class E implements I { } // parse error
|
||||
|
||||
interface A<Y> { y: Y }
|
||||
interface A_<X> { x: X }
|
||||
interface B<Z> extends A<string>, A_<Z> { z: Z }
|
||||
|
|
|
@ -69,6 +69,7 @@ React.createElement(\'bad\', {}); // This is fine
|
|||
var React = require(\"react\");
|
||||
|
||||
// The builtin $JSXIntrinsics should allow any string
|
||||
|
||||
var Div = \"div\";
|
||||
var Bad = \"bad\";
|
||||
var Str: string = \"str\";
|
||||
|
|
|
@ -65,11 +65,13 @@ class C {
|
|||
}
|
||||
|
||||
// check
|
||||
|
||||
(new C().foo(): boolean); // last wins
|
||||
(new C().x: boolean); // last wins
|
||||
(new C().bar: boolean); // last wins
|
||||
(new C().qux: boolean); // weird outlier where last doesn\'t win in classes
|
||||
// Objects
|
||||
|
||||
const o = {
|
||||
foo(): number {
|
||||
return 0;
|
||||
|
@ -90,6 +92,7 @@ const o = {
|
|||
};
|
||||
|
||||
// check
|
||||
|
||||
(o.foo(): boolean); // last wins
|
||||
(o.x: boolean); // last wins
|
||||
(o.bar: boolean); // last wins
|
||||
|
|
|
@ -37,6 +37,7 @@ var red:string = tuple[indices.red]; // error: tuple[0] is a number
|
|||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
var APIKeys = require(\"./enum\");
|
||||
// object that maps \"AGE\" to \"age\", \"NAME\" to \"name\"
|
||||
|
||||
function foo(x: $Keys<typeof APIKeys>) {}
|
||||
foo(\"AGE\");
|
||||
foo(\"LOCATION\"); // error
|
||||
|
|
|
@ -152,6 +152,7 @@ var x: string = 0;
|
|||
var x: number = 1;
|
||||
|
||||
//declare var T: $Type<number | Array<T>>;
|
||||
|
||||
function foo(p: boolean) {}
|
||||
|
||||
function sorry(really: boolean) {
|
||||
|
|
|
@ -27,6 +27,7 @@ var o3 = {};
|
|||
o3.w = o2;
|
||||
|
||||
//declare var exports: { w: any };
|
||||
|
||||
module.exports = o3;
|
||||
"
|
||||
`;
|
||||
|
|
|
@ -55,6 +55,7 @@ function foo5<T>(): Array<T> {
|
|||
var b = foo5();
|
||||
var y: string = b[0];
|
||||
*/
|
||||
|
||||
var foo6 = function<R>(x: R): R {
|
||||
return foo1(x);
|
||||
};
|
||||
|
|
|
@ -80,6 +80,7 @@ if (y instanceof A) {
|
|||
y = 0;
|
||||
}
|
||||
//f(y);
|
||||
|
||||
function bar() {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -90,6 +90,7 @@ var App = React.createClass({
|
|||
var z = this.state.z;
|
||||
|
||||
//this.state;
|
||||
|
||||
return (
|
||||
<div>
|
||||
{foo(x, y)}
|
||||
|
|
|
@ -392,6 +392,7 @@ import React from \"react\";
|
|||
//import React from \"React\";
|
||||
//var React = require(\"react\");
|
||||
//var React = require(\"React\");
|
||||
|
||||
class HelloMessage extends React.Component {
|
||||
props: { name: string };
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ fs.readFile(\"file.exp\", {}, (_, data) => {
|
|||
var fs = require(\"fs\");
|
||||
|
||||
/* readFile */
|
||||
|
||||
fs.readFile(\"file.exp\", (_, data) => {
|
||||
(data: Buffer);
|
||||
});
|
||||
|
@ -53,6 +54,7 @@ fs.readFile(\"file.exp\", {}, (_, data) => {
|
|||
});
|
||||
|
||||
/* readFileSync */
|
||||
|
||||
(fs.readFileSync(\"file.exp\"): Buffer);
|
||||
(fs.readFileSync(\"file.exp\"): string); // error
|
||||
(fs.readFileSync(\"file.exp\", \"blah\"): string);
|
||||
|
|
|
@ -412,6 +412,7 @@ var y = new Foo();
|
|||
//
|
||||
// toString
|
||||
//
|
||||
|
||||
// call
|
||||
takesAString(a.toString());
|
||||
d.toString(); // ok, even though dict specifies strings, this is a function
|
||||
|
@ -450,6 +451,7 @@ takesAString(y.toString());
|
|||
//
|
||||
// hasOwnProperty
|
||||
//
|
||||
|
||||
// call
|
||||
takesABool(a.hasOwnProperty(\"foo\"));
|
||||
|
||||
|
@ -475,6 +477,7 @@ takesABool(y.hasOwnProperty(\"foo\"));
|
|||
//
|
||||
// propertyIsEnumerable
|
||||
//
|
||||
|
||||
// call
|
||||
takesABool(a.propertyIsEnumerable(\"foo\"));
|
||||
|
||||
|
@ -500,6 +503,7 @@ takesABool(y.propertyIsEnumerable(\"foo\"));
|
|||
//
|
||||
// valueOf
|
||||
//
|
||||
|
||||
// call
|
||||
takesAnObject(a.valueOf());
|
||||
|
||||
|
@ -529,6 +533,7 @@ var boolValueOf: boolean = true.valueOf();
|
|||
//
|
||||
// toLocaleString
|
||||
//
|
||||
|
||||
// call
|
||||
takesAString(a.toLocaleString());
|
||||
|
||||
|
@ -554,6 +559,7 @@ takesAString(y.toLocaleString());
|
|||
//
|
||||
// constructor
|
||||
//
|
||||
|
||||
var k: Object = a.constructor;
|
||||
(123).constructor;
|
||||
"
|
||||
|
|
|
@ -136,6 +136,7 @@ function is_string_and_number(x, y): %checks {
|
|||
declare function refine<T, P: $Pred<1>>(v: T, cb: P): $Refine<T, P, 1>;
|
||||
// function refine(v, cb)
|
||||
// { if (cb(v)) { return v; } else { throw new Error(); } }
|
||||
|
||||
/*
|
||||
Use case
|
||||
*/
|
||||
|
@ -150,6 +151,7 @@ declare function refine_fst<T, P: $Pred<2>>(
|
|||
): $Refine<T, P, 1>;
|
||||
// function refine_fst(v, w, cb)
|
||||
// { if (cb(v, w)) { return v; } else { throw new Error(); } }
|
||||
|
||||
declare var c: mixed;
|
||||
declare var d: mixed;
|
||||
|
||||
|
@ -160,6 +162,7 @@ declare function refine2<T, P: $Pred<2>>(v: T, w: T, cb: P): $Refine<T, P, 1>;
|
|||
|
||||
// function refine_fst(v, w, cb)
|
||||
// { if (cb(v, w)) { return w; } else { throw new Error(); } }
|
||||
|
||||
function is_string(x): boolean %checks {
|
||||
return typeof x === \"string\";
|
||||
}
|
||||
|
@ -343,6 +346,7 @@ var e = refine(a, is_string_regular); // ERROR: is_string_regular is not a
|
|||
(e: number);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
function is_string(x): %checks {
|
||||
return typeof x === \"string\";
|
||||
}
|
||||
|
|
|
@ -388,6 +388,7 @@ declare function is_number(x: mixed): boolean %checks(typeof x === \"number\");
|
|||
|
||||
// Sanity check:
|
||||
// - Erroneous logic
|
||||
|
||||
function bar(x: string | Array<string>): string {
|
||||
if (is_number(x)) {
|
||||
return x;
|
||||
|
|
|
@ -412,6 +412,7 @@ new Promise(function(resolve, reject) {
|
|||
/////////////////////////////////////////////////
|
||||
// == Promise constructor reject() function == //
|
||||
/////////////////////////////////////////////////
|
||||
|
||||
// TODO: Promise constructor reject(T) -> catch(T)
|
||||
new Promise(function(resolve, reject) {
|
||||
reject(0);
|
||||
|
@ -455,6 +456,7 @@ new Promise(function(resolve, reject) {
|
|||
/////////////////////////////
|
||||
// == Promise.resolve() == //
|
||||
/////////////////////////////
|
||||
|
||||
// Promise.resolve(T) -> then(T)
|
||||
Promise.resolve(0).then(function(num) {
|
||||
var a: number = num;
|
||||
|
@ -476,6 +478,7 @@ Promise.resolve(Promise.resolve(Promise.resolve(0))).then(function(num) {
|
|||
////////////////////////////
|
||||
// == Promise.reject() == //
|
||||
////////////////////////////
|
||||
|
||||
// TODO: Promise.reject(T) -> catch(T)
|
||||
Promise.reject(0).catch(function(num) {
|
||||
var a: number = num;
|
||||
|
@ -495,6 +498,7 @@ Promise.reject(Promise.resolve(0)).then(function(num) {
|
|||
//////////////////////////////////
|
||||
// == Promise.prototype.then == //
|
||||
//////////////////////////////////
|
||||
|
||||
// resolvedPromise.then():T -> then(T)
|
||||
Promise
|
||||
.resolve(0)
|
||||
|
@ -544,6 +548,7 @@ Promise
|
|||
///////////////////////////////////
|
||||
// == Promise.prototype.catch == //
|
||||
///////////////////////////////////
|
||||
|
||||
// rejectedPromise.catch():U -> then(U)
|
||||
Promise
|
||||
.reject(0)
|
||||
|
|
|
@ -93,12 +93,14 @@ class P<X> {
|
|||
x: X;
|
||||
}
|
||||
// this is like Promise
|
||||
|
||||
type Pstar<X> = X | Pstar<P<X>>; // this is like Promise*
|
||||
var p: P<number> = new P();
|
||||
(p.x: string); // error
|
||||
var pstar: Pstar<number> = 0; // OK
|
||||
(pstar: number); // error, but limit potentially unbounded number of errors!
|
||||
// e.g., P<number> ~/~ number, P<P<number>> ~/~ number, ...
|
||||
|
||||
pstar = p; // OK
|
||||
(pstar.x: string); // error
|
||||
pstar = (new P(): P<P<number>>); // OK
|
||||
|
|
|
@ -543,6 +543,7 @@ var tests = [
|
|||
// the scope that gets merged after the if statement is the correct
|
||||
// post-condition scope, not the one that was saved at the beginning of the
|
||||
// if statement.
|
||||
|
||||
function() {
|
||||
let x: { foo: ?string } = { foo: null };
|
||||
if (!x.foo) {
|
||||
|
@ -1193,6 +1194,7 @@ function foo(a, b, c) {
|
|||
}
|
||||
|
||||
// test refis out of switches that are exhaustive without default case
|
||||
|
||||
function exhaustion1(x): number {
|
||||
var foo;
|
||||
switch (x) {
|
||||
|
@ -1574,6 +1576,7 @@ class A {
|
|||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
var undef_tests = [
|
||||
// NOTE: not (yet?) supporting non-strict eq test for undefined
|
||||
|
||||
// expr !== undefined
|
||||
function() {
|
||||
var x: ?string = \"xxx\";
|
||||
|
@ -1718,6 +1721,7 @@ class A {
|
|||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
var void_tests = [
|
||||
// NOTE: not (yet?) supporting non-strict eq test for undefined
|
||||
|
||||
// expr !== void(...)
|
||||
function() {
|
||||
var x: ?string = \"xxx\";
|
||||
|
|
|
@ -668,6 +668,7 @@ function def_assign_within_for(b: boolean, obj: Obj) {
|
|||
}
|
||||
|
||||
// --- name-sensitive havoc ---
|
||||
|
||||
type Obj2 = { q: number | string };
|
||||
|
||||
function def_assign_setprop_nohavoc(obj: Obj, obj2: Obj2) {
|
||||
|
@ -1582,6 +1583,7 @@ function e_array(x: Array<?string>): string {
|
|||
}
|
||||
|
||||
// --- name-sensitive havoc ---
|
||||
|
||||
function c2(x: { [key: string]: ?string }, y: { z: string }): string {
|
||||
if (x[y.z]) {
|
||||
y.z = \"HEY\";
|
||||
|
|
|
@ -51,6 +51,7 @@ function f(x: number) {
|
|||
return x;
|
||||
}
|
||||
//function f(x:number):string { return x; }
|
||||
|
||||
var x: string = f(0);
|
||||
|
||||
module.exports = f;
|
||||
|
@ -79,6 +80,7 @@ module.exports = o;
|
|||
|
||||
var o = { x: 0 };
|
||||
//var o: {x: number;} = { x: 0 }
|
||||
|
||||
var x: string = o.x;
|
||||
|
||||
module.exports = o;
|
||||
|
|
|
@ -35,6 +35,7 @@ function getNum() {
|
|||
// $FlowFixMe This was the second loc in the error
|
||||
var test3: string = getNum(); // This error should be suppressed
|
||||
// $FlowFixMe Error unused suppression
|
||||
|
||||
var test4: string = 123; // This error is NOT suppressed
|
||||
// $FlowFixMe Indentation shouldn\'t matter
|
||||
var test5: string = 123; // This error should be suppressed
|
||||
|
|
|
@ -86,6 +86,7 @@ foo(o2.y); // setting o3.y to 0 has no effect on o2.y
|
|||
/*
|
||||
* this bindings:
|
||||
*/
|
||||
|
||||
/* standard functions may rebind this */
|
||||
function f1(): number {
|
||||
return this.x;
|
||||
|
|
|
@ -96,6 +96,7 @@ class B extends A {
|
|||
}
|
||||
|
||||
// covariance checks on this type in invariant positions
|
||||
|
||||
class Invariant {
|
||||
out_object(): { _: this } {
|
||||
return { _: this };
|
||||
|
@ -111,6 +112,7 @@ class Invariant {
|
|||
}
|
||||
|
||||
// covariance checks on this type as type args
|
||||
|
||||
class Misc {
|
||||
// Set<X> has invariant X
|
||||
out_set(): Set<this> {
|
||||
|
@ -483,7 +485,9 @@ class InheritOverride extends Override {}
|
|||
|
||||
(new InheritOverride().bar_caller(): InheritOverride); // error
|
||||
// blame flips below
|
||||
|
||||
// Examples with \`this\` types (compare with examples above)
|
||||
|
||||
class Base2 {
|
||||
foo(): this {
|
||||
return this;
|
||||
|
@ -516,6 +520,7 @@ class Override2 extends Base2 {
|
|||
return new Override2();
|
||||
} // error (cf. OK above)
|
||||
// see exploit below
|
||||
|
||||
corge(that: this) {} // error
|
||||
// see exploit below
|
||||
grault(that: this) {} // error, too
|
||||
|
|
|
@ -22,6 +22,7 @@ function foo(x: ?string): $NonMaybeType<?string> {
|
|||
}
|
||||
|
||||
//(foo(): string); // should not be necessary to expose the error above
|
||||
|
||||
(0: $NonMaybeType<null>); // error
|
||||
(0: $NonMaybeType<?number>); // ok
|
||||
(0: $NonMaybeType<number | null>); // ok
|
||||
|
|
|
@ -22,6 +22,7 @@ module.exports = printBinaryExpression;
|
|||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
\"use babel\";
|
||||
/* @flow */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2015-present, Facebook, Inc.
|
||||
* All rights reserved.
|
||||
|
@ -29,6 +30,7 @@ module.exports = printBinaryExpression;
|
|||
* This source code is licensed under the license found in the LICENSE file in
|
||||
* the root directory of this source tree.
|
||||
*/
|
||||
|
||||
import type { BinaryExpression } from \"./types\";
|
||||
|
||||
function printBinaryExpression(node: BinaryExpression) {
|
||||
|
@ -5095,7 +5097,9 @@ export type JSXSpreadAttribute = {
|
|||
/*
|
||||
* Flow types for the Babylon AST.
|
||||
*/
|
||||
|
||||
// Abstract types. Something must extend these.
|
||||
|
||||
export type Comment =
|
||||
| {
|
||||
type: \"CommentLine\",
|
||||
|
@ -8277,6 +8281,7 @@ export type Type =
|
|||
};
|
||||
|
||||
// Concrete Types. Nothing can extend these.
|
||||
|
||||
export type CommentLine = {
|
||||
type: \"CommentLine\",
|
||||
_CommentLine: void,
|
||||
|
@ -8302,6 +8307,7 @@ export type CommentBlock = {
|
|||
};
|
||||
|
||||
// Babel concrete types.
|
||||
|
||||
export type ArrayExpression = {
|
||||
type: \"ArrayExpression\",
|
||||
_ArrayExpression: void,
|
||||
|
|
|
@ -95,6 +95,7 @@ class MyClass<T> {
|
|||
|
||||
var c: MyClass = new MyClass(0); // no error
|
||||
// no arity error in type annotation using polymorphic class with defaulting
|
||||
|
||||
class MyClass2<T, U=string> {
|
||||
x: T;
|
||||
y: U;
|
||||
|
@ -106,17 +107,21 @@ class MyClass2<T, U=string> {
|
|||
|
||||
var c2: MyClass2 = new MyClass2(0, \"\"); // no error
|
||||
// no arity error in type annotation using polymorphic type alias
|
||||
|
||||
type MyObject<T> = { x: T };
|
||||
|
||||
var o: MyObject = { x: 0 }; // no error
|
||||
// arity error in type alias rhs
|
||||
|
||||
type MySubobject = { y: number } & MyObject; // no error
|
||||
// arity error in interface extends
|
||||
|
||||
interface MyInterface<T> { x: T }
|
||||
|
||||
interface MySubinterface extends MyInterface { y: number } // no error
|
||||
|
||||
// no arity error in extends of polymorphic class
|
||||
|
||||
class MySubclass
|
||||
extends MyClass { // ok, type arg inferred
|
||||
y: number;
|
||||
|
@ -126,6 +131,7 @@ class MySubclass
|
|||
}
|
||||
|
||||
// no arity error in call of polymorphic function
|
||||
|
||||
function singleton<T>(x: T): Array<T> {
|
||||
return [x];
|
||||
}
|
||||
|
|
|
@ -93,6 +93,7 @@ class MyClass<T> {
|
|||
|
||||
var c: MyClass = new MyClass(0); // error, missing argument list (1)
|
||||
// arity error in type annotation using polymorphic class with defaulting
|
||||
|
||||
class MyClass2<T, U=string> {
|
||||
x: T;
|
||||
y: U;
|
||||
|
@ -104,17 +105,21 @@ class MyClass2<T, U=string> {
|
|||
|
||||
var c2: MyClass2 = new MyClass2(0, \"\"); // error, missing argument list (1-2)
|
||||
// arity error in type annotation using polymorphic type alias
|
||||
|
||||
type MyObject<T> = { x: T };
|
||||
|
||||
var o: MyObject = { x: 0 }; // error, missing argument list
|
||||
// arity error in type alias rhs
|
||||
|
||||
type MySubobject = { y: number } & MyObject; // error, missing argument list
|
||||
// arity error in interface extends
|
||||
|
||||
interface MyInterface<T> { x: T }
|
||||
|
||||
interface MySubinterface extends MyInterface { y: number } // error, missing argument list
|
||||
|
||||
// *no* arity error in extends of polymorphic class
|
||||
|
||||
class MySubclass
|
||||
extends MyClass { // ok, type arg inferred
|
||||
y: number;
|
||||
|
@ -124,6 +129,7 @@ class MySubclass
|
|||
}
|
||||
|
||||
// *no* arity error in call of polymorphic function
|
||||
|
||||
function singleton<T>(x: T): Array<T> {
|
||||
return [x];
|
||||
}
|
||||
|
|
|
@ -132,6 +132,7 @@ declare class E<T> { m<T>(x: T): E<T> }
|
|||
declare class F<T> extends E<T> { m<T>(x: T): F<T> }
|
||||
|
||||
// Bounds can refer to parent type params (until they are shadowed).
|
||||
|
||||
class G<T> {
|
||||
x: T;
|
||||
constructor(x: T) {
|
||||
|
@ -147,6 +148,7 @@ g.m(0); // ok
|
|||
g.m(true); // err, bool ~> number|string
|
||||
(g.m(\"\"): G<number>); // err, string ~> number
|
||||
// Shadow bounds incompatible with parent
|
||||
|
||||
class H<T> {
|
||||
x: T;
|
||||
m<T>(x: T) {
|
||||
|
|
|
@ -107,6 +107,7 @@ var a: MyClass1 = new MyClass1();
|
|||
// Following tests are errors which conflate the type
|
||||
// of the class value itself with the type of its
|
||||
// instances.
|
||||
|
||||
// Aside: it\'s worth staring at the following (correct)
|
||||
// type annotations until they make sense:
|
||||
//
|
||||
|
@ -121,6 +122,7 @@ var a: MyClass1 = new MyClass1();
|
|||
// The second says that objects produced by the MyClass1
|
||||
// constructor function have type MyClass1 - the type of
|
||||
// instances of MyClass1.
|
||||
|
||||
// Error: assign the actual MyClass1 value to a variable
|
||||
// whose annotated type is of instances of MyClass1.
|
||||
//
|
||||
|
@ -141,12 +143,14 @@ var c: typeof MyClass2 = new MyClass2();
|
|||
//////////////////////////////////////
|
||||
// == typeof <<non-class value>> == //
|
||||
//////////////////////////////////////
|
||||
|
||||
var numValue: number = 42;
|
||||
var d: typeof numValue = 100;
|
||||
var e: typeof numValue = \"asdf\"; // Error: string ~> number
|
||||
/////////////////////////////////
|
||||
// == typeof <<type-alias>> == //
|
||||
/////////////////////////////////
|
||||
|
||||
type numberAlias = number;
|
||||
|
||||
// This is an error because typeof takes a value, not
|
||||
|
@ -159,6 +163,7 @@ var f: typeof numberAlias = 42; // Error: \'typeof <<type-alias>>\' makes no sen
|
|||
* These provoke a specific error, not just the generic
|
||||
* \"type is incompatible\"
|
||||
*/
|
||||
|
||||
var Map = { A: \"this is A\", B: \"this is B\", C: \"this is C\" };
|
||||
var keys: $Keys<Map> = \"A\"; // Error: ineligible value used in type anno
|
||||
"
|
||||
|
|
|
@ -327,6 +327,7 @@ function hello(x:X): string {
|
|||
|
||||
type X = ({ a: true } & { b: string }) | ({ a: false } & { c: string });
|
||||
//type X = {a:true, b:string} | {a:false, c:string}; // this works.
|
||||
|
||||
function hello(x: X): string {
|
||||
if (x.a === true) return x.b;
|
||||
else return x.c;
|
||||
|
@ -459,6 +460,7 @@ const obj_result = obj({ x: \"\" }); // currently an error! (expect it to be OK)
|
|||
// blocks until A1 is partially resolved. Since the argument partially matches
|
||||
// A1, that branch is selected. Later, that branch errors, but other branches
|
||||
// have been lost by then.
|
||||
|
||||
type A1 = { x: B1 };
|
||||
type A2 = { x: B2 };
|
||||
|
||||
|
@ -470,6 +472,7 @@ type B2 = string;
|
|||
///////////////////////////////////////
|
||||
// similar example with function types
|
||||
///////////////////////////////////////
|
||||
|
||||
function fun(a: A3 | A4) {
|
||||
return a();
|
||||
}
|
||||
|
@ -487,6 +490,7 @@ type B4 = string;
|
|||
/////////////////////////////////////////////
|
||||
// similar example with class instance types
|
||||
/////////////////////////////////////////////
|
||||
|
||||
function inst(a: A5 | A6) {}
|
||||
|
||||
class B5 {}
|
||||
|
@ -598,6 +602,7 @@ type B1 = string;
|
|||
///////////////////////////////////////
|
||||
// similar example with function types
|
||||
///////////////////////////////////////
|
||||
|
||||
function fun(a: (() => number) | (() => string)) {}
|
||||
|
||||
fun((() => \"\": A2));
|
||||
|
@ -609,6 +614,7 @@ type B2 = string;
|
|||
/////////////////////////////////////////////////////
|
||||
// similar example with generic class instance types
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
class C<X> {}
|
||||
|
||||
function inst(a: C<number> | C<string>) {}
|
||||
|
@ -622,6 +628,7 @@ type B3 = string;
|
|||
/////////////////////////////////////////////
|
||||
// similar example with generic type aliases
|
||||
/////////////////////////////////////////////
|
||||
|
||||
function alias(a: T<number> | T<string>) {}
|
||||
alias({ x: (x: V<B4>) => {} });
|
||||
|
||||
|
@ -632,6 +639,7 @@ type V<X> = X;
|
|||
type B4 = string;
|
||||
|
||||
// class statics
|
||||
|
||||
function stat(a: { x: number } | { x: string }) {}
|
||||
|
||||
class D {
|
||||
|
@ -643,6 +651,7 @@ stat(D);
|
|||
type B5 = string;
|
||||
|
||||
// tuples
|
||||
|
||||
function tup(a: [number, boolean] | [string, boolean]) {}
|
||||
|
||||
tup(([\"\", false]: A6));
|
||||
|
@ -704,6 +713,7 @@ type B1 = string;
|
|||
////////////////////////////
|
||||
// example with array types
|
||||
////////////////////////////
|
||||
|
||||
function arr(a: number[] | string[]) {}
|
||||
|
||||
arr(([]: A2));
|
||||
|
@ -778,6 +788,7 @@ type B1 = string;
|
|||
////////////////////////////
|
||||
// example with array types
|
||||
////////////////////////////
|
||||
|
||||
function arr(a: number[] | string[]) {}
|
||||
|
||||
const a2 = ([]: A2);
|
||||
|
@ -849,6 +860,7 @@ function fun_call(x: string): string {
|
|||
/////////////////////////////
|
||||
// example with array types
|
||||
/////////////////////////////
|
||||
|
||||
function arr(a: number[] | string[]) {}
|
||||
|
||||
var a2 = [];
|
||||
|
@ -971,6 +983,7 @@ type H2 = number;
|
|||
///////////////////////////////
|
||||
// polymorphic recursive types
|
||||
///////////////////////////////
|
||||
|
||||
function polyrec(x: PF<number> | PF<string>) {}
|
||||
rec({ x: 0 });
|
||||
|
||||
|
@ -1150,6 +1163,7 @@ function id<X>(x: X): X {
|
|||
/////////////////////////
|
||||
// primitive annotations
|
||||
/////////////////////////
|
||||
|
||||
function check_prim(_: number | string) {}
|
||||
|
||||
// ok
|
||||
|
@ -1161,6 +1175,7 @@ check_prim(id(\"\"));
|
|||
//////////////////////////////
|
||||
// class instance annotations
|
||||
//////////////////////////////
|
||||
|
||||
class C {}
|
||||
class D {}
|
||||
function check_inst(_: C | D) {}
|
||||
|
@ -1174,6 +1189,7 @@ check_inst(id(new C()));
|
|||
////////////////////////
|
||||
// function annotations
|
||||
////////////////////////
|
||||
|
||||
function check_fun(_: ((_: number) => number) | ((_: string) => string)) {}
|
||||
|
||||
// help!
|
||||
|
@ -1182,6 +1198,7 @@ check_fun(x => x);
|
|||
//////////////////////
|
||||
// object annotations
|
||||
//////////////////////
|
||||
|
||||
function check_obj(_: { x: number } | { x: string }) {}
|
||||
|
||||
// ok
|
||||
|
@ -1193,6 +1210,7 @@ check_obj({ x: id(\"\") });
|
|||
/////////////////////
|
||||
// array annotations
|
||||
/////////////////////
|
||||
|
||||
function check_arr(_: number[] | string[]) {}
|
||||
|
||||
// ok
|
||||
|
@ -1204,6 +1222,7 @@ check_arr([id(\"\")]);
|
|||
//////////////////////////////////////
|
||||
// generic class instance annotations
|
||||
//////////////////////////////////////
|
||||
|
||||
class P<X> {}
|
||||
function check_poly_inst(_: P<number> | P<string>) {}
|
||||
|
||||
|
@ -1374,6 +1393,7 @@ type EventHandler = (event: Event) => mixed;
|
|||
type KeyboardEventHandler = (event: KeyboardEvent) => mixed;
|
||||
|
||||
// example where globals are not yet resolved
|
||||
|
||||
function bar(x: (() => void) | { x: number }) {}
|
||||
|
||||
bar(() => {});
|
||||
|
@ -1814,6 +1834,7 @@ function hello4(x:X): string {
|
|||
|
||||
type X = ({ a: true } & { b: string }) | ({ a: false } & { c: string });
|
||||
//type X = {a:true, b:string} | {a:false, c:string}; // this works.
|
||||
|
||||
function hello1(x: X): string {
|
||||
if (x.a === true) return x.b;
|
||||
else return x.c;
|
||||
|
|
|
@ -35,6 +35,7 @@ function test1(): string {
|
|||
|
||||
// regression test for analysis after abnormal control flow:
|
||||
// consts must not become bot (EmptyT).
|
||||
|
||||
function test2() {
|
||||
const n = 0;
|
||||
|
||||
|
|
Loading…
Reference in New Issue