Always enable evolving types in Javascript files

This commit is contained in:
Nathan Shively-Sanders 2016-11-18 14:13:56 -08:00
parent a4d584f14a
commit 7750fe1a7c
5 changed files with 780 additions and 2 deletions

View file

@ -3238,10 +3238,10 @@ namespace ts {
return addOptionality(getTypeFromTypeNode(declaration.type), /*optional*/ declaration.questionToken && includeOptionality);
}
if (compilerOptions.noImplicitAny &&
if ((compilerOptions.noImplicitAny || declaration.flags & NodeFlags.JavaScriptFile) &&
declaration.kind === SyntaxKind.VariableDeclaration && !isBindingPattern(declaration.name) &&
!(getCombinedModifierFlags(declaration) & ModifierFlags.Export) && !isInAmbientContext(declaration)) {
// If --noImplicitAny is on,
// If --noImplicitAny is on or the declaration is in a Javascript file,
// use control flow tracked 'any' type for non-ambient, non-exported var or let variables with no
// initializer or a 'null' or 'undefined' initializer.
if (!(getCombinedNodeFlags(declaration) & NodeFlags.Const) && (!declaration.initializer || isNullOrUndefined(declaration.initializer))) {

View file

@ -0,0 +1,203 @@
//// [controlFlowJavascript.js]
let cond = true;
// CFA for 'let' and no initializer
function f1() {
let x;
if (cond) {
x = 1;
}
if (cond) {
x = "hello";
}
const y = x; // string | number | undefined
}
// CFA for 'let' and 'undefined' initializer
function f2() {
let x = undefined;
if (cond) {
x = 1;
}
if (cond) {
x = "hello";
}
const y = x; // string | number | undefined
}
// CFA for 'let' and 'null' initializer
function f3() {
let x = null;
if (cond) {
x = 1;
}
if (cond) {
x = "hello";
}
const y = x; // string | number | null
}
// CFA for 'var' with no initializer
function f5() {
var x;
if (cond) {
x = 1;
}
if (cond) {
x = "hello";
}
const y = x; // string | number | undefined
}
// CFA for 'var' with 'undefined' initializer
function f6() {
var x = undefined;
if (cond) {
x = 1;
}
if (cond) {
x = "hello";
}
const y = x; // string | number | undefined
}
// CFA for 'var' with 'null' initializer
function f7() {
var x = null;
if (cond) {
x = 1;
}
if (cond) {
x = "hello";
}
const y = x; // string | number | null
}
// No CFA for captured outer variables
function f9() {
let x;
if (cond) {
x = 1;
}
if (cond) {
x = "hello";
}
const y = x; // string | number | undefined
function f() {
const z = x; // any
}
}
// No CFA for captured outer variables
function f10() {
let x;
if (cond) {
x = 1;
}
if (cond) {
x = "hello";
}
const y = x; // string | number | undefined
const f = () => {
const z = x; // any
};
}
//// [out.js]
var cond = true;
// CFA for 'let' and no initializer
function f1() {
var x;
if (cond) {
x = 1;
}
if (cond) {
x = "hello";
}
var y = x; // string | number | undefined
}
// CFA for 'let' and 'undefined' initializer
function f2() {
var x = undefined;
if (cond) {
x = 1;
}
if (cond) {
x = "hello";
}
var y = x; // string | number | undefined
}
// CFA for 'let' and 'null' initializer
function f3() {
var x = null;
if (cond) {
x = 1;
}
if (cond) {
x = "hello";
}
var y = x; // string | number | null
}
// CFA for 'var' with no initializer
function f5() {
var x;
if (cond) {
x = 1;
}
if (cond) {
x = "hello";
}
var y = x; // string | number | undefined
}
// CFA for 'var' with 'undefined' initializer
function f6() {
var x = undefined;
if (cond) {
x = 1;
}
if (cond) {
x = "hello";
}
var y = x; // string | number | undefined
}
// CFA for 'var' with 'null' initializer
function f7() {
var x = null;
if (cond) {
x = 1;
}
if (cond) {
x = "hello";
}
var y = x; // string | number | null
}
// No CFA for captured outer variables
function f9() {
var x;
if (cond) {
x = 1;
}
if (cond) {
x = "hello";
}
var y = x; // string | number | undefined
function f() {
var z = x; // any
}
}
// No CFA for captured outer variables
function f10() {
var x;
if (cond) {
x = 1;
}
if (cond) {
x = "hello";
}
var y = x; // string | number | undefined
var f = function () {
var z = x; // any
};
}

View file

@ -0,0 +1,216 @@
=== tests/cases/compiler/controlFlowJavascript.js ===
let cond = true;
>cond : Symbol(cond, Decl(controlFlowJavascript.js, 1, 3))
// CFA for 'let' and no initializer
function f1() {
>f1 : Symbol(f1, Decl(controlFlowJavascript.js, 1, 16))
let x;
>x : Symbol(x, Decl(controlFlowJavascript.js, 5, 7))
if (cond) {
>cond : Symbol(cond, Decl(controlFlowJavascript.js, 1, 3))
x = 1;
>x : Symbol(x, Decl(controlFlowJavascript.js, 5, 7))
}
if (cond) {
>cond : Symbol(cond, Decl(controlFlowJavascript.js, 1, 3))
x = "hello";
>x : Symbol(x, Decl(controlFlowJavascript.js, 5, 7))
}
const y = x; // string | number | undefined
>y : Symbol(y, Decl(controlFlowJavascript.js, 12, 9))
>x : Symbol(x, Decl(controlFlowJavascript.js, 5, 7))
}
// CFA for 'let' and 'undefined' initializer
function f2() {
>f2 : Symbol(f2, Decl(controlFlowJavascript.js, 13, 1))
let x = undefined;
>x : Symbol(x, Decl(controlFlowJavascript.js, 17, 7))
>undefined : Symbol(undefined)
if (cond) {
>cond : Symbol(cond, Decl(controlFlowJavascript.js, 1, 3))
x = 1;
>x : Symbol(x, Decl(controlFlowJavascript.js, 17, 7))
}
if (cond) {
>cond : Symbol(cond, Decl(controlFlowJavascript.js, 1, 3))
x = "hello";
>x : Symbol(x, Decl(controlFlowJavascript.js, 17, 7))
}
const y = x; // string | number | undefined
>y : Symbol(y, Decl(controlFlowJavascript.js, 24, 9))
>x : Symbol(x, Decl(controlFlowJavascript.js, 17, 7))
}
// CFA for 'let' and 'null' initializer
function f3() {
>f3 : Symbol(f3, Decl(controlFlowJavascript.js, 25, 1))
let x = null;
>x : Symbol(x, Decl(controlFlowJavascript.js, 29, 7))
if (cond) {
>cond : Symbol(cond, Decl(controlFlowJavascript.js, 1, 3))
x = 1;
>x : Symbol(x, Decl(controlFlowJavascript.js, 29, 7))
}
if (cond) {
>cond : Symbol(cond, Decl(controlFlowJavascript.js, 1, 3))
x = "hello";
>x : Symbol(x, Decl(controlFlowJavascript.js, 29, 7))
}
const y = x; // string | number | null
>y : Symbol(y, Decl(controlFlowJavascript.js, 36, 9))
>x : Symbol(x, Decl(controlFlowJavascript.js, 29, 7))
}
// CFA for 'var' with no initializer
function f5() {
>f5 : Symbol(f5, Decl(controlFlowJavascript.js, 37, 1))
var x;
>x : Symbol(x, Decl(controlFlowJavascript.js, 41, 7))
if (cond) {
>cond : Symbol(cond, Decl(controlFlowJavascript.js, 1, 3))
x = 1;
>x : Symbol(x, Decl(controlFlowJavascript.js, 41, 7))
}
if (cond) {
>cond : Symbol(cond, Decl(controlFlowJavascript.js, 1, 3))
x = "hello";
>x : Symbol(x, Decl(controlFlowJavascript.js, 41, 7))
}
const y = x; // string | number | undefined
>y : Symbol(y, Decl(controlFlowJavascript.js, 48, 9))
>x : Symbol(x, Decl(controlFlowJavascript.js, 41, 7))
}
// CFA for 'var' with 'undefined' initializer
function f6() {
>f6 : Symbol(f6, Decl(controlFlowJavascript.js, 49, 1))
var x = undefined;
>x : Symbol(x, Decl(controlFlowJavascript.js, 53, 7))
>undefined : Symbol(undefined)
if (cond) {
>cond : Symbol(cond, Decl(controlFlowJavascript.js, 1, 3))
x = 1;
>x : Symbol(x, Decl(controlFlowJavascript.js, 53, 7))
}
if (cond) {
>cond : Symbol(cond, Decl(controlFlowJavascript.js, 1, 3))
x = "hello";
>x : Symbol(x, Decl(controlFlowJavascript.js, 53, 7))
}
const y = x; // string | number | undefined
>y : Symbol(y, Decl(controlFlowJavascript.js, 60, 9))
>x : Symbol(x, Decl(controlFlowJavascript.js, 53, 7))
}
// CFA for 'var' with 'null' initializer
function f7() {
>f7 : Symbol(f7, Decl(controlFlowJavascript.js, 61, 1))
var x = null;
>x : Symbol(x, Decl(controlFlowJavascript.js, 65, 7))
if (cond) {
>cond : Symbol(cond, Decl(controlFlowJavascript.js, 1, 3))
x = 1;
>x : Symbol(x, Decl(controlFlowJavascript.js, 65, 7))
}
if (cond) {
>cond : Symbol(cond, Decl(controlFlowJavascript.js, 1, 3))
x = "hello";
>x : Symbol(x, Decl(controlFlowJavascript.js, 65, 7))
}
const y = x; // string | number | null
>y : Symbol(y, Decl(controlFlowJavascript.js, 72, 9))
>x : Symbol(x, Decl(controlFlowJavascript.js, 65, 7))
}
// No CFA for captured outer variables
function f9() {
>f9 : Symbol(f9, Decl(controlFlowJavascript.js, 73, 1))
let x;
>x : Symbol(x, Decl(controlFlowJavascript.js, 77, 7))
if (cond) {
>cond : Symbol(cond, Decl(controlFlowJavascript.js, 1, 3))
x = 1;
>x : Symbol(x, Decl(controlFlowJavascript.js, 77, 7))
}
if (cond) {
>cond : Symbol(cond, Decl(controlFlowJavascript.js, 1, 3))
x = "hello";
>x : Symbol(x, Decl(controlFlowJavascript.js, 77, 7))
}
const y = x; // string | number | undefined
>y : Symbol(y, Decl(controlFlowJavascript.js, 84, 9))
>x : Symbol(x, Decl(controlFlowJavascript.js, 77, 7))
function f() {
>f : Symbol(f, Decl(controlFlowJavascript.js, 84, 16))
const z = x; // any
>z : Symbol(z, Decl(controlFlowJavascript.js, 86, 13))
>x : Symbol(x, Decl(controlFlowJavascript.js, 77, 7))
}
}
// No CFA for captured outer variables
function f10() {
>f10 : Symbol(f10, Decl(controlFlowJavascript.js, 88, 1))
let x;
>x : Symbol(x, Decl(controlFlowJavascript.js, 92, 7))
if (cond) {
>cond : Symbol(cond, Decl(controlFlowJavascript.js, 1, 3))
x = 1;
>x : Symbol(x, Decl(controlFlowJavascript.js, 92, 7))
}
if (cond) {
>cond : Symbol(cond, Decl(controlFlowJavascript.js, 1, 3))
x = "hello";
>x : Symbol(x, Decl(controlFlowJavascript.js, 92, 7))
}
const y = x; // string | number | undefined
>y : Symbol(y, Decl(controlFlowJavascript.js, 99, 9))
>x : Symbol(x, Decl(controlFlowJavascript.js, 92, 7))
const f = () => {
>f : Symbol(f, Decl(controlFlowJavascript.js, 100, 9))
const z = x; // any
>z : Symbol(z, Decl(controlFlowJavascript.js, 101, 13))
>x : Symbol(x, Decl(controlFlowJavascript.js, 92, 7))
};
}

View file

@ -0,0 +1,252 @@
=== tests/cases/compiler/controlFlowJavascript.js ===
let cond = true;
>cond : boolean
>true : true
// CFA for 'let' and no initializer
function f1() {
>f1 : () => void
let x;
>x : any
if (cond) {
>cond : boolean
x = 1;
>x = 1 : 1
>x : any
>1 : 1
}
if (cond) {
>cond : boolean
x = "hello";
>x = "hello" : "hello"
>x : any
>"hello" : "hello"
}
const y = x; // string | number | undefined
>y : string | number
>x : string | number
}
// CFA for 'let' and 'undefined' initializer
function f2() {
>f2 : () => void
let x = undefined;
>x : any
>undefined : undefined
if (cond) {
>cond : boolean
x = 1;
>x = 1 : 1
>x : any
>1 : 1
}
if (cond) {
>cond : boolean
x = "hello";
>x = "hello" : "hello"
>x : any
>"hello" : "hello"
}
const y = x; // string | number | undefined
>y : string | number
>x : string | number
}
// CFA for 'let' and 'null' initializer
function f3() {
>f3 : () => void
let x = null;
>x : any
>null : null
if (cond) {
>cond : boolean
x = 1;
>x = 1 : 1
>x : any
>1 : 1
}
if (cond) {
>cond : boolean
x = "hello";
>x = "hello" : "hello"
>x : any
>"hello" : "hello"
}
const y = x; // string | number | null
>y : string | number
>x : string | number
}
// CFA for 'var' with no initializer
function f5() {
>f5 : () => void
var x;
>x : any
if (cond) {
>cond : boolean
x = 1;
>x = 1 : 1
>x : any
>1 : 1
}
if (cond) {
>cond : boolean
x = "hello";
>x = "hello" : "hello"
>x : any
>"hello" : "hello"
}
const y = x; // string | number | undefined
>y : string | number
>x : string | number
}
// CFA for 'var' with 'undefined' initializer
function f6() {
>f6 : () => void
var x = undefined;
>x : any
>undefined : undefined
if (cond) {
>cond : boolean
x = 1;
>x = 1 : 1
>x : any
>1 : 1
}
if (cond) {
>cond : boolean
x = "hello";
>x = "hello" : "hello"
>x : any
>"hello" : "hello"
}
const y = x; // string | number | undefined
>y : string | number
>x : string | number
}
// CFA for 'var' with 'null' initializer
function f7() {
>f7 : () => void
var x = null;
>x : any
>null : null
if (cond) {
>cond : boolean
x = 1;
>x = 1 : 1
>x : any
>1 : 1
}
if (cond) {
>cond : boolean
x = "hello";
>x = "hello" : "hello"
>x : any
>"hello" : "hello"
}
const y = x; // string | number | null
>y : string | number
>x : string | number
}
// No CFA for captured outer variables
function f9() {
>f9 : () => void
let x;
>x : any
if (cond) {
>cond : boolean
x = 1;
>x = 1 : 1
>x : any
>1 : 1
}
if (cond) {
>cond : boolean
x = "hello";
>x = "hello" : "hello"
>x : any
>"hello" : "hello"
}
const y = x; // string | number | undefined
>y : string | number
>x : string | number
function f() {
>f : () => void
const z = x; // any
>z : any
>x : any
}
}
// No CFA for captured outer variables
function f10() {
>f10 : () => void
let x;
>x : any
if (cond) {
>cond : boolean
x = 1;
>x = 1 : 1
>x : any
>1 : 1
}
if (cond) {
>cond : boolean
x = "hello";
>x = "hello" : "hello"
>x : any
>"hello" : "hello"
}
const y = x; // string | number | undefined
>y : string | number
>x : string | number
const f = () => {
>f : () => void
>() => { const z = x; // any } : () => void
const z = x; // any
>z : any
>x : any
};
}

View file

@ -0,0 +1,107 @@
// @allowJs: true
// @Filename: controlFlowJavascript.js
// @out: out.js
let cond = true;
// CFA for 'let' and no initializer
function f1() {
let x;
if (cond) {
x = 1;
}
if (cond) {
x = "hello";
}
const y = x; // string | number | undefined
}
// CFA for 'let' and 'undefined' initializer
function f2() {
let x = undefined;
if (cond) {
x = 1;
}
if (cond) {
x = "hello";
}
const y = x; // string | number | undefined
}
// CFA for 'let' and 'null' initializer
function f3() {
let x = null;
if (cond) {
x = 1;
}
if (cond) {
x = "hello";
}
const y = x; // string | number | null
}
// CFA for 'var' with no initializer
function f5() {
var x;
if (cond) {
x = 1;
}
if (cond) {
x = "hello";
}
const y = x; // string | number | undefined
}
// CFA for 'var' with 'undefined' initializer
function f6() {
var x = undefined;
if (cond) {
x = 1;
}
if (cond) {
x = "hello";
}
const y = x; // string | number | undefined
}
// CFA for 'var' with 'null' initializer
function f7() {
var x = null;
if (cond) {
x = 1;
}
if (cond) {
x = "hello";
}
const y = x; // string | number | null
}
// No CFA for captured outer variables
function f9() {
let x;
if (cond) {
x = 1;
}
if (cond) {
x = "hello";
}
const y = x; // string | number | undefined
function f() {
const z = x; // any
}
}
// No CFA for captured outer variables
function f10() {
let x;
if (cond) {
x = 1;
}
if (cond) {
x = "hello";
}
const y = x; // string | number | undefined
const f = () => {
const z = x; // any
};
}