fix(43030): fix instantiated null/undefined type from JS initializer (#43933)
This commit is contained in:
parent
bb6d8a716e
commit
463c79440f
|
@ -20025,9 +20025,13 @@ namespace ts {
|
|||
return (type as TypeReference).cachedEquivalentBaseType = instantiatedBase;
|
||||
}
|
||||
|
||||
function isEmptyLiteralType(type: Type): boolean {
|
||||
return strictNullChecks ? type === implicitNeverType : type === undefinedWideningType;
|
||||
}
|
||||
|
||||
function isEmptyArrayLiteralType(type: Type): boolean {
|
||||
const elementType = getElementTypeOfArrayType(type);
|
||||
return strictNullChecks ? elementType === implicitNeverType : elementType === undefinedWideningType;
|
||||
return !!elementType && isEmptyLiteralType(elementType);
|
||||
}
|
||||
|
||||
function isTupleLikeType(type: Type): boolean {
|
||||
|
@ -32355,7 +32359,7 @@ namespace ts {
|
|||
function widenTypeInferredFromInitializer(declaration: HasExpressionInitializer, type: Type) {
|
||||
const widened = getCombinedNodeFlags(declaration) & NodeFlags.Const || isDeclarationReadonly(declaration) ? type : getWidenedLiteralType(type);
|
||||
if (isInJSFile(declaration)) {
|
||||
if (widened.flags & TypeFlags.Nullable) {
|
||||
if (isEmptyLiteralType(widened)) {
|
||||
reportImplicitAny(declaration, anyType);
|
||||
return anyType;
|
||||
}
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
tests/cases/conformance/salsa/a.js(3,5): error TS7008: Member 'unknown' implicitly has an 'any' type.
|
||||
tests/cases/conformance/salsa/a.js(4,5): error TS7008: Member 'unknowable' implicitly has an 'any' type.
|
||||
tests/cases/conformance/salsa/a.js(5,5): error TS7008: Member 'empty' implicitly has an 'any[]' type.
|
||||
tests/cases/conformance/salsa/a.js(25,12): error TS7006: Parameter 'a' implicitly has an 'any' type.
|
||||
tests/cases/conformance/salsa/a.js(25,29): error TS7006: Parameter 'l' implicitly has an 'any[]' type.
|
||||
tests/cases/conformance/salsa/a.js(27,5): error TS2322: Type 'undefined' is not assignable to type 'null'.
|
||||
tests/cases/conformance/salsa/a.js(29,5): error TS2322: Type '1' is not assignable to type 'null'.
|
||||
tests/cases/conformance/salsa/a.js(30,5): error TS2322: Type 'true' is not assignable to type 'null'.
|
||||
tests/cases/conformance/salsa/a.js(31,5): error TS2322: Type '{}' is not assignable to type 'null'.
|
||||
tests/cases/conformance/salsa/a.js(32,5): error TS2322: Type '"ok"' is not assignable to type 'null'.
|
||||
tests/cases/conformance/salsa/a.js(37,5): error TS2322: Type '"error"' is not assignable to type 'number | undefined'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/salsa/a.js (6 errors) ====
|
||||
==== tests/cases/conformance/salsa/a.js (10 errors) ====
|
||||
function A () {
|
||||
// should get any on this-assignments in constructor
|
||||
this.unknown = null
|
||||
|
@ -38,17 +42,25 @@ tests/cases/conformance/salsa/a.js(37,5): error TS2322: Type '"error"' is not as
|
|||
|
||||
// should get any on parameter initialisers
|
||||
function f(a = null, b = n, l = []) {
|
||||
~~~~~~~~
|
||||
!!! error TS7006: Parameter 'a' implicitly has an 'any' type.
|
||||
~~~~~~
|
||||
!!! error TS7006: Parameter 'l' implicitly has an 'any[]' type.
|
||||
// a should be any
|
||||
// a should be null in strict mode
|
||||
a = undefined
|
||||
~
|
||||
!!! error TS2322: Type 'undefined' is not assignable to type 'null'.
|
||||
a = null
|
||||
a = 1
|
||||
~
|
||||
!!! error TS2322: Type '1' is not assignable to type 'null'.
|
||||
a = true
|
||||
~
|
||||
!!! error TS2322: Type 'true' is not assignable to type 'null'.
|
||||
a = {}
|
||||
~
|
||||
!!! error TS2322: Type '{}' is not assignable to type 'null'.
|
||||
a = 'ok'
|
||||
~
|
||||
!!! error TS2322: Type '"ok"' is not assignable to type 'null'.
|
||||
|
||||
// b should be number | undefined, not any
|
||||
b = 1
|
||||
|
@ -77,6 +89,6 @@ tests/cases/conformance/salsa/a.js(37,5): error TS2322: Type '"error"' is not as
|
|||
const isUndef = v => v === undefined;
|
||||
const e = [1, undefined];
|
||||
|
||||
// should be undefined[]
|
||||
// should be undefined[]
|
||||
const g = e.filter(isUndef);
|
||||
|
|
@ -103,7 +103,7 @@ function f(a = null, b = n, l = []) {
|
|||
>n : Symbol(n, Decl(a.js, 21, 3))
|
||||
>l : Symbol(l, Decl(a.js, 24, 27))
|
||||
|
||||
// a should be any
|
||||
// a should be null in strict mode
|
||||
a = undefined
|
||||
>a : Symbol(a, Decl(a.js, 24, 11))
|
||||
>undefined : Symbol(undefined)
|
||||
|
@ -186,7 +186,7 @@ const e = [1, undefined];
|
|||
>e : Symbol(e, Decl(a.js, 56, 5))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
// should be undefined[]
|
||||
// should be undefined[]
|
||||
const g = e.filter(isUndef);
|
||||
>g : Symbol(g, Decl(a.js, 59, 5))
|
||||
>e.filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
|
||||
|
|
|
@ -127,43 +127,43 @@ var n;
|
|||
|
||||
// should get any on parameter initialisers
|
||||
function f(a = null, b = n, l = []) {
|
||||
>f : (a?: any, b?: number | undefined, l?: any[]) => void
|
||||
>a : any
|
||||
>f : (a?: null, b?: number | undefined, l?: any[]) => void
|
||||
>a : null
|
||||
>null : null
|
||||
>b : number | undefined
|
||||
>n : number | undefined
|
||||
>l : any[]
|
||||
>[] : never[]
|
||||
|
||||
// a should be any
|
||||
// a should be null in strict mode
|
||||
a = undefined
|
||||
>a = undefined : undefined
|
||||
>a : any
|
||||
>a : null
|
||||
>undefined : undefined
|
||||
|
||||
a = null
|
||||
>a = null : null
|
||||
>a : any
|
||||
>a : null
|
||||
>null : null
|
||||
|
||||
a = 1
|
||||
>a = 1 : 1
|
||||
>a : any
|
||||
>a : null
|
||||
>1 : 1
|
||||
|
||||
a = true
|
||||
>a = true : true
|
||||
>a : any
|
||||
>a : null
|
||||
>true : true
|
||||
|
||||
a = {}
|
||||
>a = {} : {}
|
||||
>a : any
|
||||
>a : null
|
||||
>{} : {}
|
||||
|
||||
a = 'ok'
|
||||
>a = 'ok' : "ok"
|
||||
>a : any
|
||||
>a : null
|
||||
>'ok' : "ok"
|
||||
|
||||
// b should be number | undefined, not any
|
||||
|
@ -254,7 +254,7 @@ const e = [1, undefined];
|
|||
>1 : 1
|
||||
>undefined : undefined
|
||||
|
||||
// should be undefined[]
|
||||
// should be undefined[]
|
||||
const g = e.filter(isUndef);
|
||||
>g : undefined[]
|
||||
>e.filter(isUndef) : undefined[]
|
||||
|
|
22
tests/baselines/reference/typeFromJSInitializer2.symbols
Normal file
22
tests/baselines/reference/typeFromJSInitializer2.symbols
Normal file
|
@ -0,0 +1,22 @@
|
|||
=== tests/cases/conformance/salsa/a.js ===
|
||||
/** @type {() => undefined} */
|
||||
function f1() {
|
||||
>f1 : Symbol(f1, Decl(a.js, 0, 0))
|
||||
|
||||
return undefined;
|
||||
>undefined : Symbol(undefined)
|
||||
}
|
||||
const a = f1()
|
||||
>a : Symbol(a, Decl(a.js, 4, 5))
|
||||
>f1 : Symbol(f1, Decl(a.js, 0, 0))
|
||||
|
||||
/** @type {() => null} */
|
||||
function f2() {
|
||||
>f2 : Symbol(f2, Decl(a.js, 4, 14))
|
||||
|
||||
return null;
|
||||
}
|
||||
const b = f2()
|
||||
>b : Symbol(b, Decl(a.js, 10, 5))
|
||||
>f2 : Symbol(f2, Decl(a.js, 4, 14))
|
||||
|
25
tests/baselines/reference/typeFromJSInitializer2.types
Normal file
25
tests/baselines/reference/typeFromJSInitializer2.types
Normal file
|
@ -0,0 +1,25 @@
|
|||
=== tests/cases/conformance/salsa/a.js ===
|
||||
/** @type {() => undefined} */
|
||||
function f1() {
|
||||
>f1 : () => undefined
|
||||
|
||||
return undefined;
|
||||
>undefined : undefined
|
||||
}
|
||||
const a = f1()
|
||||
>a : undefined
|
||||
>f1() : undefined
|
||||
>f1 : () => undefined
|
||||
|
||||
/** @type {() => null} */
|
||||
function f2() {
|
||||
>f2 : () => null
|
||||
|
||||
return null;
|
||||
>null : null
|
||||
}
|
||||
const b = f2()
|
||||
>b : null
|
||||
>f2() : null
|
||||
>f2 : () => null
|
||||
|
22
tests/baselines/reference/typeFromJSInitializer3.symbols
Normal file
22
tests/baselines/reference/typeFromJSInitializer3.symbols
Normal file
|
@ -0,0 +1,22 @@
|
|||
=== tests/cases/conformance/salsa/a.js ===
|
||||
/** @type {() => undefined} */
|
||||
function f1() {
|
||||
>f1 : Symbol(f1, Decl(a.js, 0, 0))
|
||||
|
||||
return undefined;
|
||||
>undefined : Symbol(undefined)
|
||||
}
|
||||
const a = f1()
|
||||
>a : Symbol(a, Decl(a.js, 4, 5))
|
||||
>f1 : Symbol(f1, Decl(a.js, 0, 0))
|
||||
|
||||
/** @type {() => null} */
|
||||
function f2() {
|
||||
>f2 : Symbol(f2, Decl(a.js, 4, 14))
|
||||
|
||||
return null;
|
||||
}
|
||||
const b = f2()
|
||||
>b : Symbol(b, Decl(a.js, 10, 5))
|
||||
>f2 : Symbol(f2, Decl(a.js, 4, 14))
|
||||
|
25
tests/baselines/reference/typeFromJSInitializer3.types
Normal file
25
tests/baselines/reference/typeFromJSInitializer3.types
Normal file
|
@ -0,0 +1,25 @@
|
|||
=== tests/cases/conformance/salsa/a.js ===
|
||||
/** @type {() => undefined} */
|
||||
function f1() {
|
||||
>f1 : () => undefined
|
||||
|
||||
return undefined;
|
||||
>undefined : undefined
|
||||
}
|
||||
const a = f1()
|
||||
>a : undefined
|
||||
>f1() : undefined
|
||||
>f1 : () => undefined
|
||||
|
||||
/** @type {() => null} */
|
||||
function f2() {
|
||||
>f2 : () => null
|
||||
|
||||
return null;
|
||||
>null : null
|
||||
}
|
||||
const b = f2()
|
||||
>b : null
|
||||
>f2() : null
|
||||
>f2 : () => null
|
||||
|
35
tests/baselines/reference/typeFromJSInitializer4.errors.txt
Normal file
35
tests/baselines/reference/typeFromJSInitializer4.errors.txt
Normal file
|
@ -0,0 +1,35 @@
|
|||
tests/cases/conformance/salsa/a.js(5,12): error TS7006: Parameter 'a' implicitly has an 'any' type.
|
||||
tests/cases/conformance/salsa/a.js(5,29): error TS7006: Parameter 'l' implicitly has an 'any[]' type.
|
||||
tests/cases/conformance/salsa/a.js(17,5): error TS2322: Type 'string' is not assignable to type 'number'.
|
||||
|
||||
|
||||
==== tests/cases/conformance/salsa/a.js (3 errors) ====
|
||||
/** @type {number | undefined} */
|
||||
var n;
|
||||
|
||||
// should get any on parameter initialisers
|
||||
function f(a = null, b = n, l = []) {
|
||||
~~~~~~~~
|
||||
!!! error TS7006: Parameter 'a' implicitly has an 'any' type.
|
||||
~~~~~~
|
||||
!!! error TS7006: Parameter 'l' implicitly has an 'any[]' type.
|
||||
// a should be any
|
||||
a = undefined
|
||||
a = null
|
||||
a = 1
|
||||
a = true
|
||||
a = {}
|
||||
a = 'ok'
|
||||
|
||||
// b should be number | undefined, not any
|
||||
b = 1
|
||||
b = undefined
|
||||
b = 'error'
|
||||
~
|
||||
!!! error TS2322: Type 'string' is not assignable to type 'number'.
|
||||
|
||||
// l should be any[]
|
||||
l.push(1)
|
||||
l.push('ok')
|
||||
}
|
||||
|
56
tests/baselines/reference/typeFromJSInitializer4.symbols
Normal file
56
tests/baselines/reference/typeFromJSInitializer4.symbols
Normal file
|
@ -0,0 +1,56 @@
|
|||
=== tests/cases/conformance/salsa/a.js ===
|
||||
/** @type {number | undefined} */
|
||||
var n;
|
||||
>n : Symbol(n, Decl(a.js, 1, 3))
|
||||
|
||||
// should get any on parameter initialisers
|
||||
function f(a = null, b = n, l = []) {
|
||||
>f : Symbol(f, Decl(a.js, 1, 6))
|
||||
>a : Symbol(a, Decl(a.js, 4, 11))
|
||||
>b : Symbol(b, Decl(a.js, 4, 20))
|
||||
>n : Symbol(n, Decl(a.js, 1, 3))
|
||||
>l : Symbol(l, Decl(a.js, 4, 27))
|
||||
|
||||
// a should be any
|
||||
a = undefined
|
||||
>a : Symbol(a, Decl(a.js, 4, 11))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
a = null
|
||||
>a : Symbol(a, Decl(a.js, 4, 11))
|
||||
|
||||
a = 1
|
||||
>a : Symbol(a, Decl(a.js, 4, 11))
|
||||
|
||||
a = true
|
||||
>a : Symbol(a, Decl(a.js, 4, 11))
|
||||
|
||||
a = {}
|
||||
>a : Symbol(a, Decl(a.js, 4, 11))
|
||||
|
||||
a = 'ok'
|
||||
>a : Symbol(a, Decl(a.js, 4, 11))
|
||||
|
||||
// b should be number | undefined, not any
|
||||
b = 1
|
||||
>b : Symbol(b, Decl(a.js, 4, 20))
|
||||
|
||||
b = undefined
|
||||
>b : Symbol(b, Decl(a.js, 4, 20))
|
||||
>undefined : Symbol(undefined)
|
||||
|
||||
b = 'error'
|
||||
>b : Symbol(b, Decl(a.js, 4, 20))
|
||||
|
||||
// l should be any[]
|
||||
l.push(1)
|
||||
>l.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --))
|
||||
>l : Symbol(l, Decl(a.js, 4, 27))
|
||||
>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --))
|
||||
|
||||
l.push('ok')
|
||||
>l.push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --))
|
||||
>l : Symbol(l, Decl(a.js, 4, 27))
|
||||
>push : Symbol(Array.push, Decl(lib.es5.d.ts, --, --))
|
||||
}
|
||||
|
78
tests/baselines/reference/typeFromJSInitializer4.types
Normal file
78
tests/baselines/reference/typeFromJSInitializer4.types
Normal file
|
@ -0,0 +1,78 @@
|
|||
=== tests/cases/conformance/salsa/a.js ===
|
||||
/** @type {number | undefined} */
|
||||
var n;
|
||||
>n : number
|
||||
|
||||
// should get any on parameter initialisers
|
||||
function f(a = null, b = n, l = []) {
|
||||
>f : (a?: any, b?: number, l?: any[]) => void
|
||||
>a : any
|
||||
>null : null
|
||||
>b : number
|
||||
>n : number
|
||||
>l : any[]
|
||||
>[] : undefined[]
|
||||
|
||||
// a should be any
|
||||
a = undefined
|
||||
>a = undefined : undefined
|
||||
>a : any
|
||||
>undefined : undefined
|
||||
|
||||
a = null
|
||||
>a = null : null
|
||||
>a : any
|
||||
>null : null
|
||||
|
||||
a = 1
|
||||
>a = 1 : 1
|
||||
>a : any
|
||||
>1 : 1
|
||||
|
||||
a = true
|
||||
>a = true : true
|
||||
>a : any
|
||||
>true : true
|
||||
|
||||
a = {}
|
||||
>a = {} : {}
|
||||
>a : any
|
||||
>{} : {}
|
||||
|
||||
a = 'ok'
|
||||
>a = 'ok' : "ok"
|
||||
>a : any
|
||||
>'ok' : "ok"
|
||||
|
||||
// b should be number | undefined, not any
|
||||
b = 1
|
||||
>b = 1 : 1
|
||||
>b : number
|
||||
>1 : 1
|
||||
|
||||
b = undefined
|
||||
>b = undefined : undefined
|
||||
>b : number
|
||||
>undefined : undefined
|
||||
|
||||
b = 'error'
|
||||
>b = 'error' : "error"
|
||||
>b : number
|
||||
>'error' : "error"
|
||||
|
||||
// l should be any[]
|
||||
l.push(1)
|
||||
>l.push(1) : number
|
||||
>l.push : (...items: any[]) => number
|
||||
>l : any[]
|
||||
>push : (...items: any[]) => number
|
||||
>1 : 1
|
||||
|
||||
l.push('ok')
|
||||
>l.push('ok') : number
|
||||
>l.push : (...items: any[]) => number
|
||||
>l : any[]
|
||||
>push : (...items: any[]) => number
|
||||
>'ok' : "ok"
|
||||
}
|
||||
|
|
@ -29,7 +29,7 @@ var n;
|
|||
|
||||
// should get any on parameter initialisers
|
||||
function f(a = null, b = n, l = []) {
|
||||
// a should be any
|
||||
// a should be null in strict mode
|
||||
a = undefined
|
||||
a = null
|
||||
a = 1
|
||||
|
@ -62,5 +62,5 @@ l.push('ok')
|
|||
const isUndef = v => v === undefined;
|
||||
const e = [1, undefined];
|
||||
|
||||
// should be undefined[]
|
||||
// should be undefined[]
|
||||
const g = e.filter(isUndef);
|
||||
|
|
18
tests/cases/conformance/salsa/typeFromJSInitializer2.ts
Normal file
18
tests/cases/conformance/salsa/typeFromJSInitializer2.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
// @allowJs: true
|
||||
// @checkJs: true
|
||||
// @noEmit: true
|
||||
// @strictNullChecks: true
|
||||
// @noImplicitAny: true
|
||||
// @Filename: a.js
|
||||
|
||||
/** @type {() => undefined} */
|
||||
function f1() {
|
||||
return undefined;
|
||||
}
|
||||
const a = f1()
|
||||
|
||||
/** @type {() => null} */
|
||||
function f2() {
|
||||
return null;
|
||||
}
|
||||
const b = f2()
|
18
tests/cases/conformance/salsa/typeFromJSInitializer3.ts
Normal file
18
tests/cases/conformance/salsa/typeFromJSInitializer3.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
// @allowJs: true
|
||||
// @checkJs: true
|
||||
// @noEmit: true
|
||||
// @strictNullChecks: false
|
||||
// @noImplicitAny: true
|
||||
// @Filename: a.js
|
||||
|
||||
/** @type {() => undefined} */
|
||||
function f1() {
|
||||
return undefined;
|
||||
}
|
||||
const a = f1()
|
||||
|
||||
/** @type {() => null} */
|
||||
function f2() {
|
||||
return null;
|
||||
}
|
||||
const b = f2()
|
29
tests/cases/conformance/salsa/typeFromJSInitializer4.ts
Normal file
29
tests/cases/conformance/salsa/typeFromJSInitializer4.ts
Normal file
|
@ -0,0 +1,29 @@
|
|||
// @allowJs: true
|
||||
// @checkJs: true
|
||||
// @noEmit: true
|
||||
// @strictNullChecks: false
|
||||
// @noImplicitAny: true
|
||||
// @Filename: a.js
|
||||
|
||||
/** @type {number | undefined} */
|
||||
var n;
|
||||
|
||||
// should get any on parameter initialisers
|
||||
function f(a = null, b = n, l = []) {
|
||||
// a should be any
|
||||
a = undefined
|
||||
a = null
|
||||
a = 1
|
||||
a = true
|
||||
a = {}
|
||||
a = 'ok'
|
||||
|
||||
// b should be number | undefined, not any
|
||||
b = 1
|
||||
b = undefined
|
||||
b = 'error'
|
||||
|
||||
// l should be any[]
|
||||
l.push(1)
|
||||
l.push('ok')
|
||||
}
|
Loading…
Reference in a new issue