feat: support error when comparing with object/array literals (#45978)

* feat: support error when comparing with object/array literals

* chore: include regexp, function and class literal

* chore: include regexp, function and class literal

* test: update baseline

* fix: baseline
This commit is contained in:
Jack Works 2022-05-13 06:45:22 +08:00 committed by GitHub
parent da00ba67ed
commit b689cd0aa9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 768 additions and 3 deletions

View File

@ -33977,6 +33977,10 @@ namespace ts {
case SyntaxKind.ExclamationEqualsToken:
case SyntaxKind.EqualsEqualsEqualsToken:
case SyntaxKind.ExclamationEqualsEqualsToken:
if (isLiteralExpressionOfObject(left) || isLiteralExpressionOfObject(right)) {
const eqType = operator === SyntaxKind.EqualsEqualsToken || operator === SyntaxKind.EqualsEqualsEqualsToken;
error(errorNode, Diagnostics.This_condition_will_always_return_0_since_JavaScript_compares_objects_by_reference_not_value, eqType ? "false" : "true");
}
reportOperatorErrorUnless((left, right) => isTypeEqualityComparableTo(left, right) || isTypeEqualityComparableTo(right, left));
return booleanType;

View File

@ -3459,6 +3459,10 @@
"category": "Error",
"code": 2838
},
"This condition will always return '{0}' since JavaScript compares objects by reference, not value.": {
"category": "Error",
"code": 2839
},
"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",

View File

@ -1114,6 +1114,19 @@ namespace ts {
return isLiteralKind(node.kind);
}
/** @internal */
export function isLiteralExpressionOfObject(node: Node) {
switch (node.kind) {
case SyntaxKind.ObjectLiteralExpression:
case SyntaxKind.ArrayLiteralExpression:
case SyntaxKind.RegularExpressionLiteral:
case SyntaxKind.FunctionExpression:
case SyntaxKind.ClassExpression:
return true;
}
return false;
}
// Pseudo-literals
/* @internal */

View File

@ -0,0 +1,130 @@
tests/cases/compiler/conditionalEqualityOnLiteralObjects.ts(4,5): error TS2839: This condition will always return 'false' since JavaScript compares objects by reference, not value.
tests/cases/compiler/conditionalEqualityOnLiteralObjects.ts(6,5): error TS2839: This condition will always return 'false' since JavaScript compares objects by reference, not value.
tests/cases/compiler/conditionalEqualityOnLiteralObjects.ts(8,5): error TS2839: This condition will always return 'false' since JavaScript compares objects by reference, not value.
tests/cases/compiler/conditionalEqualityOnLiteralObjects.ts(10,5): error TS2839: This condition will always return 'false' since JavaScript compares objects by reference, not value.
tests/cases/compiler/conditionalEqualityOnLiteralObjects.ts(12,5): error TS2839: This condition will always return 'false' since JavaScript compares objects by reference, not value.
tests/cases/compiler/conditionalEqualityOnLiteralObjects.ts(14,5): error TS2839: This condition will always return 'false' since JavaScript compares objects by reference, not value.
tests/cases/compiler/conditionalEqualityOnLiteralObjects.ts(17,5): error TS2839: This condition will always return 'true' since JavaScript compares objects by reference, not value.
tests/cases/compiler/conditionalEqualityOnLiteralObjects.ts(19,5): error TS2839: This condition will always return 'true' since JavaScript compares objects by reference, not value.
tests/cases/compiler/conditionalEqualityOnLiteralObjects.ts(21,5): error TS2839: This condition will always return 'true' since JavaScript compares objects by reference, not value.
tests/cases/compiler/conditionalEqualityOnLiteralObjects.ts(23,5): error TS2839: This condition will always return 'true' since JavaScript compares objects by reference, not value.
tests/cases/compiler/conditionalEqualityOnLiteralObjects.ts(25,5): error TS2839: This condition will always return 'true' since JavaScript compares objects by reference, not value.
tests/cases/compiler/conditionalEqualityOnLiteralObjects.ts(27,5): error TS2839: This condition will always return 'true' since JavaScript compares objects by reference, not value.
tests/cases/compiler/conditionalEqualityOnLiteralObjects.ts(30,5): error TS2839: This condition will always return 'false' since JavaScript compares objects by reference, not value.
tests/cases/compiler/conditionalEqualityOnLiteralObjects.ts(32,5): error TS2839: This condition will always return 'false' since JavaScript compares objects by reference, not value.
tests/cases/compiler/conditionalEqualityOnLiteralObjects.ts(34,5): error TS2839: This condition will always return 'false' since JavaScript compares objects by reference, not value.
tests/cases/compiler/conditionalEqualityOnLiteralObjects.ts(36,5): error TS2839: This condition will always return 'false' since JavaScript compares objects by reference, not value.
tests/cases/compiler/conditionalEqualityOnLiteralObjects.ts(38,5): error TS2839: This condition will always return 'false' since JavaScript compares objects by reference, not value.
tests/cases/compiler/conditionalEqualityOnLiteralObjects.ts(40,5): error TS2839: This condition will always return 'false' since JavaScript compares objects by reference, not value.
tests/cases/compiler/conditionalEqualityOnLiteralObjects.ts(43,5): error TS2839: This condition will always return 'true' since JavaScript compares objects by reference, not value.
tests/cases/compiler/conditionalEqualityOnLiteralObjects.ts(45,5): error TS2839: This condition will always return 'true' since JavaScript compares objects by reference, not value.
tests/cases/compiler/conditionalEqualityOnLiteralObjects.ts(47,5): error TS2839: This condition will always return 'true' since JavaScript compares objects by reference, not value.
tests/cases/compiler/conditionalEqualityOnLiteralObjects.ts(49,5): error TS2839: This condition will always return 'true' since JavaScript compares objects by reference, not value.
tests/cases/compiler/conditionalEqualityOnLiteralObjects.ts(51,5): error TS2839: This condition will always return 'true' since JavaScript compares objects by reference, not value.
tests/cases/compiler/conditionalEqualityOnLiteralObjects.ts(53,5): error TS2839: This condition will always return 'true' since JavaScript compares objects by reference, not value.
==== tests/cases/compiler/conditionalEqualityOnLiteralObjects.ts (24 errors) ====
const a = { a: 1 }
const b = [1]
if ({ a: 1 } === { a: 1 }) {
~~~~~~~~~~~~~~~~~~~~~
!!! error TS2839: This condition will always return 'false' since JavaScript compares objects by reference, not value.
}
if ([1] === [1]) {
~~~~~~~~~~~
!!! error TS2839: This condition will always return 'false' since JavaScript compares objects by reference, not value.
}
if (a === { a: 1 }) {
~~~~~~~~~~~~~~
!!! error TS2839: This condition will always return 'false' since JavaScript compares objects by reference, not value.
}
if (b === [1]) {
~~~~~~~~~
!!! error TS2839: This condition will always return 'false' since JavaScript compares objects by reference, not value.
}
if ({ a: 1 } === a) {
~~~~~~~~~~~~~~
!!! error TS2839: This condition will always return 'false' since JavaScript compares objects by reference, not value.
}
if ([1] === b) {
~~~~~~~~~
!!! error TS2839: This condition will always return 'false' since JavaScript compares objects by reference, not value.
}
if ({ a: 1 } !== { a: 1 }) {
~~~~~~~~~~~~~~~~~~~~~
!!! error TS2839: This condition will always return 'true' since JavaScript compares objects by reference, not value.
}
if ([1] !== [1]) {
~~~~~~~~~~~
!!! error TS2839: This condition will always return 'true' since JavaScript compares objects by reference, not value.
}
if (a !== { a: 1 }) {
~~~~~~~~~~~~~~
!!! error TS2839: This condition will always return 'true' since JavaScript compares objects by reference, not value.
}
if (b !== [1]) {
~~~~~~~~~
!!! error TS2839: This condition will always return 'true' since JavaScript compares objects by reference, not value.
}
if ({ a: 1 } !== a) {
~~~~~~~~~~~~~~
!!! error TS2839: This condition will always return 'true' since JavaScript compares objects by reference, not value.
}
if ([1] !== b) {
~~~~~~~~~
!!! error TS2839: This condition will always return 'true' since JavaScript compares objects by reference, not value.
}
if ({ a: 1 } == { a: 1 }) {
~~~~~~~~~~~~~~~~~~~~
!!! error TS2839: This condition will always return 'false' since JavaScript compares objects by reference, not value.
}
if ([1] == [1]) {
~~~~~~~~~~
!!! error TS2839: This condition will always return 'false' since JavaScript compares objects by reference, not value.
}
if (a == { a: 1 }) {
~~~~~~~~~~~~~
!!! error TS2839: This condition will always return 'false' since JavaScript compares objects by reference, not value.
}
if (b == [1]) {
~~~~~~~~
!!! error TS2839: This condition will always return 'false' since JavaScript compares objects by reference, not value.
}
if ({ a: 1 } == a) {
~~~~~~~~~~~~~
!!! error TS2839: This condition will always return 'false' since JavaScript compares objects by reference, not value.
}
if ([1] == b) {
~~~~~~~~
!!! error TS2839: This condition will always return 'false' since JavaScript compares objects by reference, not value.
}
if ({ a: 1 } != { a: 1 }) {
~~~~~~~~~~~~~~~~~~~~
!!! error TS2839: This condition will always return 'true' since JavaScript compares objects by reference, not value.
}
if ([1] != [1]) {
~~~~~~~~~~
!!! error TS2839: This condition will always return 'true' since JavaScript compares objects by reference, not value.
}
if (a != { a: 1 }) {
~~~~~~~~~~~~~
!!! error TS2839: This condition will always return 'true' since JavaScript compares objects by reference, not value.
}
if (b != [1]) {
~~~~~~~~
!!! error TS2839: This condition will always return 'true' since JavaScript compares objects by reference, not value.
}
if ({ a: 1 } != a) {
~~~~~~~~~~~~~
!!! error TS2839: This condition will always return 'true' since JavaScript compares objects by reference, not value.
}
if ([1] != b) {
~~~~~~~~
!!! error TS2839: This condition will always return 'true' since JavaScript compares objects by reference, not value.
}

View File

@ -0,0 +1,108 @@
//// [conditionalEqualityOnLiteralObjects.ts]
const a = { a: 1 }
const b = [1]
if ({ a: 1 } === { a: 1 }) {
}
if ([1] === [1]) {
}
if (a === { a: 1 }) {
}
if (b === [1]) {
}
if ({ a: 1 } === a) {
}
if ([1] === b) {
}
if ({ a: 1 } !== { a: 1 }) {
}
if ([1] !== [1]) {
}
if (a !== { a: 1 }) {
}
if (b !== [1]) {
}
if ({ a: 1 } !== a) {
}
if ([1] !== b) {
}
if ({ a: 1 } == { a: 1 }) {
}
if ([1] == [1]) {
}
if (a == { a: 1 }) {
}
if (b == [1]) {
}
if ({ a: 1 } == a) {
}
if ([1] == b) {
}
if ({ a: 1 } != { a: 1 }) {
}
if ([1] != [1]) {
}
if (a != { a: 1 }) {
}
if (b != [1]) {
}
if ({ a: 1 } != a) {
}
if ([1] != b) {
}
//// [conditionalEqualityOnLiteralObjects.js]
var a = { a: 1 };
var b = [1];
if ({ a: 1 } === { a: 1 }) {
}
if ([1] === [1]) {
}
if (a === { a: 1 }) {
}
if (b === [1]) {
}
if ({ a: 1 } === a) {
}
if ([1] === b) {
}
if ({ a: 1 } !== { a: 1 }) {
}
if ([1] !== [1]) {
}
if (a !== { a: 1 }) {
}
if (b !== [1]) {
}
if ({ a: 1 } !== a) {
}
if ([1] !== b) {
}
if ({ a: 1 } == { a: 1 }) {
}
if ([1] == [1]) {
}
if (a == { a: 1 }) {
}
if (b == [1]) {
}
if ({ a: 1 } == a) {
}
if ([1] == b) {
}
if ({ a: 1 } != { a: 1 }) {
}
if ([1] != [1]) {
}
if (a != { a: 1 }) {
}
if (b != [1]) {
}
if ({ a: 1 } != a) {
}
if ([1] != b) {
}

View File

@ -0,0 +1,92 @@
=== tests/cases/compiler/conditionalEqualityOnLiteralObjects.ts ===
const a = { a: 1 }
>a : Symbol(a, Decl(conditionalEqualityOnLiteralObjects.ts, 0, 5))
>a : Symbol(a, Decl(conditionalEqualityOnLiteralObjects.ts, 0, 11))
const b = [1]
>b : Symbol(b, Decl(conditionalEqualityOnLiteralObjects.ts, 1, 5))
if ({ a: 1 } === { a: 1 }) {
>a : Symbol(a, Decl(conditionalEqualityOnLiteralObjects.ts, 3, 5))
>a : Symbol(a, Decl(conditionalEqualityOnLiteralObjects.ts, 3, 18))
}
if ([1] === [1]) {
}
if (a === { a: 1 }) {
>a : Symbol(a, Decl(conditionalEqualityOnLiteralObjects.ts, 0, 5))
>a : Symbol(a, Decl(conditionalEqualityOnLiteralObjects.ts, 7, 11))
}
if (b === [1]) {
>b : Symbol(b, Decl(conditionalEqualityOnLiteralObjects.ts, 1, 5))
}
if ({ a: 1 } === a) {
>a : Symbol(a, Decl(conditionalEqualityOnLiteralObjects.ts, 11, 5))
>a : Symbol(a, Decl(conditionalEqualityOnLiteralObjects.ts, 0, 5))
}
if ([1] === b) {
>b : Symbol(b, Decl(conditionalEqualityOnLiteralObjects.ts, 1, 5))
}
if ({ a: 1 } !== { a: 1 }) {
>a : Symbol(a, Decl(conditionalEqualityOnLiteralObjects.ts, 16, 5))
>a : Symbol(a, Decl(conditionalEqualityOnLiteralObjects.ts, 16, 18))
}
if ([1] !== [1]) {
}
if (a !== { a: 1 }) {
>a : Symbol(a, Decl(conditionalEqualityOnLiteralObjects.ts, 0, 5))
>a : Symbol(a, Decl(conditionalEqualityOnLiteralObjects.ts, 20, 11))
}
if (b !== [1]) {
>b : Symbol(b, Decl(conditionalEqualityOnLiteralObjects.ts, 1, 5))
}
if ({ a: 1 } !== a) {
>a : Symbol(a, Decl(conditionalEqualityOnLiteralObjects.ts, 24, 5))
>a : Symbol(a, Decl(conditionalEqualityOnLiteralObjects.ts, 0, 5))
}
if ([1] !== b) {
>b : Symbol(b, Decl(conditionalEqualityOnLiteralObjects.ts, 1, 5))
}
if ({ a: 1 } == { a: 1 }) {
>a : Symbol(a, Decl(conditionalEqualityOnLiteralObjects.ts, 29, 5))
>a : Symbol(a, Decl(conditionalEqualityOnLiteralObjects.ts, 29, 17))
}
if ([1] == [1]) {
}
if (a == { a: 1 }) {
>a : Symbol(a, Decl(conditionalEqualityOnLiteralObjects.ts, 0, 5))
>a : Symbol(a, Decl(conditionalEqualityOnLiteralObjects.ts, 33, 10))
}
if (b == [1]) {
>b : Symbol(b, Decl(conditionalEqualityOnLiteralObjects.ts, 1, 5))
}
if ({ a: 1 } == a) {
>a : Symbol(a, Decl(conditionalEqualityOnLiteralObjects.ts, 37, 5))
>a : Symbol(a, Decl(conditionalEqualityOnLiteralObjects.ts, 0, 5))
}
if ([1] == b) {
>b : Symbol(b, Decl(conditionalEqualityOnLiteralObjects.ts, 1, 5))
}
if ({ a: 1 } != { a: 1 }) {
>a : Symbol(a, Decl(conditionalEqualityOnLiteralObjects.ts, 42, 5))
>a : Symbol(a, Decl(conditionalEqualityOnLiteralObjects.ts, 42, 17))
}
if ([1] != [1]) {
}
if (a != { a: 1 }) {
>a : Symbol(a, Decl(conditionalEqualityOnLiteralObjects.ts, 0, 5))
>a : Symbol(a, Decl(conditionalEqualityOnLiteralObjects.ts, 46, 10))
}
if (b != [1]) {
>b : Symbol(b, Decl(conditionalEqualityOnLiteralObjects.ts, 1, 5))
}
if ({ a: 1 } != a) {
>a : Symbol(a, Decl(conditionalEqualityOnLiteralObjects.ts, 50, 5))
>a : Symbol(a, Decl(conditionalEqualityOnLiteralObjects.ts, 0, 5))
}
if ([1] != b) {
>b : Symbol(b, Decl(conditionalEqualityOnLiteralObjects.ts, 1, 5))
}

View File

@ -0,0 +1,184 @@
=== tests/cases/compiler/conditionalEqualityOnLiteralObjects.ts ===
const a = { a: 1 }
>a : { a: number; }
>{ a: 1 } : { a: number; }
>a : number
>1 : 1
const b = [1]
>b : number[]
>[1] : number[]
>1 : 1
if ({ a: 1 } === { a: 1 }) {
>{ a: 1 } === { a: 1 } : boolean
>{ a: 1 } : { a: number; }
>a : number
>1 : 1
>{ a: 1 } : { a: number; }
>a : number
>1 : 1
}
if ([1] === [1]) {
>[1] === [1] : boolean
>[1] : number[]
>1 : 1
>[1] : number[]
>1 : 1
}
if (a === { a: 1 }) {
>a === { a: 1 } : boolean
>a : { a: number; }
>{ a: 1 } : { a: number; }
>a : number
>1 : 1
}
if (b === [1]) {
>b === [1] : boolean
>b : number[]
>[1] : number[]
>1 : 1
}
if ({ a: 1 } === a) {
>{ a: 1 } === a : boolean
>{ a: 1 } : { a: number; }
>a : number
>1 : 1
>a : { a: number; }
}
if ([1] === b) {
>[1] === b : boolean
>[1] : number[]
>1 : 1
>b : number[]
}
if ({ a: 1 } !== { a: 1 }) {
>{ a: 1 } !== { a: 1 } : boolean
>{ a: 1 } : { a: number; }
>a : number
>1 : 1
>{ a: 1 } : { a: number; }
>a : number
>1 : 1
}
if ([1] !== [1]) {
>[1] !== [1] : boolean
>[1] : number[]
>1 : 1
>[1] : number[]
>1 : 1
}
if (a !== { a: 1 }) {
>a !== { a: 1 } : boolean
>a : { a: number; }
>{ a: 1 } : { a: number; }
>a : number
>1 : 1
}
if (b !== [1]) {
>b !== [1] : boolean
>b : number[]
>[1] : number[]
>1 : 1
}
if ({ a: 1 } !== a) {
>{ a: 1 } !== a : boolean
>{ a: 1 } : { a: number; }
>a : number
>1 : 1
>a : { a: number; }
}
if ([1] !== b) {
>[1] !== b : boolean
>[1] : number[]
>1 : 1
>b : number[]
}
if ({ a: 1 } == { a: 1 }) {
>{ a: 1 } == { a: 1 } : boolean
>{ a: 1 } : { a: number; }
>a : number
>1 : 1
>{ a: 1 } : { a: number; }
>a : number
>1 : 1
}
if ([1] == [1]) {
>[1] == [1] : boolean
>[1] : number[]
>1 : 1
>[1] : number[]
>1 : 1
}
if (a == { a: 1 }) {
>a == { a: 1 } : boolean
>a : { a: number; }
>{ a: 1 } : { a: number; }
>a : number
>1 : 1
}
if (b == [1]) {
>b == [1] : boolean
>b : number[]
>[1] : number[]
>1 : 1
}
if ({ a: 1 } == a) {
>{ a: 1 } == a : boolean
>{ a: 1 } : { a: number; }
>a : number
>1 : 1
>a : { a: number; }
}
if ([1] == b) {
>[1] == b : boolean
>[1] : number[]
>1 : 1
>b : number[]
}
if ({ a: 1 } != { a: 1 }) {
>{ a: 1 } != { a: 1 } : boolean
>{ a: 1 } : { a: number; }
>a : number
>1 : 1
>{ a: 1 } : { a: number; }
>a : number
>1 : 1
}
if ([1] != [1]) {
>[1] != [1] : boolean
>[1] : number[]
>1 : 1
>[1] : number[]
>1 : 1
}
if (a != { a: 1 }) {
>a != { a: 1 } : boolean
>a : { a: number; }
>{ a: 1 } : { a: number; }
>a : number
>1 : 1
}
if (b != [1]) {
>b != [1] : boolean
>b : number[]
>[1] : number[]
>1 : 1
}
if ({ a: 1 } != a) {
>{ a: 1 } != a : boolean
>{ a: 1 } : { a: number; }
>a : number
>1 : 1
>a : { a: number; }
}
if ([1] != b) {
>[1] != b : boolean
>[1] : number[]
>1 : 1
>b : number[]
}

View File

@ -1,9 +1,10 @@
tests/cases/conformance/functions/functionImplementationErrors.ts(25,16): error TS2355: A function whose declared type is neither 'void' nor 'any' must return a value.
tests/cases/conformance/functions/functionImplementationErrors.ts(30,17): error TS2373: Parameter 'n' cannot reference identifier 'm' declared after it.
tests/cases/conformance/functions/functionImplementationErrors.ts(35,17): error TS2373: Parameter 'n' cannot reference identifier 'm' declared after it.
tests/cases/conformance/functions/functionImplementationErrors.ts(40,1): error TS2839: This condition will always return 'false' since JavaScript compares objects by reference, not value.
==== tests/cases/conformance/functions/functionImplementationErrors.ts (3 errors) ====
==== tests/cases/conformance/functions/functionImplementationErrors.ts (4 errors) ====
// FunctionExpression with no return type annotation with multiple return statements with unrelated types
var f1 = function () {
return '';
@ -50,9 +51,14 @@ tests/cases/conformance/functions/functionImplementationErrors.ts(35,17): error
// FunctionExpression with non -void return type annotation with a throw, no return, and other code
// Should be error but isn't
undefined === function (): number {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
throw undefined;
~~~~~~~~~~~~~~~~~~~~
var x = 4;
~~~~~~~~~~~~~~
};
~
!!! error TS2839: This condition will always return 'false' since JavaScript compares objects by reference, not value.
class Base { private x; }
class AnotherClass { private y; }

View File

@ -0,0 +1,164 @@
tests/cases/conformance/functions/functionImplementations.ts(90,1): error TS2839: This condition will always return 'false' since JavaScript compares objects by reference, not value.
==== tests/cases/conformance/functions/functionImplementations.ts (1 errors) ====
// FunctionExpression with no return type annotation and no return statement returns void
var v: void = function () { } ();
// FunctionExpression f with no return type annotation and directly references f in its body returns any
var a: any = function f() {
return f;
};
var a: any = function f() {
return f();
};
// FunctionExpression f with no return type annotation and indirectly references f in its body returns any
var a: any = function f() {
var x = f;
return x;
};
// Two mutually recursive function implementations with no return type annotations
function rec1() {
return rec2();
}
function rec2() {
return rec1();
}
var a = rec1();
var a = rec2();
// Two mutually recursive function implementations with return type annotation in one
function rec3(): number {
return rec4();
}
function rec4() {
return rec3();
}
var n: number;
var n = rec3();
var n = rec4();
// FunctionExpression with no return type annotation and returns a number
var n = function () {
return 3;
} ();
// FunctionExpression with no return type annotation and returns null
var nu = null;
var nu = function () {
return null;
} ();
// FunctionExpression with no return type annotation and returns undefined
var un = undefined;
var un = function () {
return undefined;
} ();
// FunctionExpression with no return type annotation and returns a type parameter type
var n = function <T>(x: T) {
return x;
} (4);
// FunctionExpression with no return type annotation and returns a constrained type parameter type
var n = function <T extends {}>(x: T) {
return x;
} (4);
// FunctionExpression with no return type annotation with multiple return statements with identical types
var n = function () {
return 3;
return 5;
}();
// Otherwise, the inferred return type is the first of the types of the return statement expressions
// in the function body that is a supertype of each of the others,
// ignoring return statements with no expressions.
// A compile - time error occurs if no return statement expression has a type that is a supertype of each of the others.
// FunctionExpression with no return type annotation with multiple return statements with subtype relation between returns
class Base { private m; }
class Derived extends Base { private q; }
var b: Base;
var b = function () {
return new Base(); return new Derived();
} ();
// FunctionExpression with no return type annotation with multiple return statements with one a recursive call
var a = function f() {
return new Base(); return new Derived(); return f(); // ?
} ();
// FunctionExpression with non -void return type annotation with a single throw statement
undefined === function (): number {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
throw undefined;
~~~~~~~~~~~~~~~~~~~~
};
~
!!! error TS2839: This condition will always return 'false' since JavaScript compares objects by reference, not value.
// Type of 'this' in function implementation is 'any'
function thisFunc() {
var x = this;
var x: any;
}
// Function signature with optional parameter, no type annotation and initializer has initializer's type
function opt1(n = 4) {
var m = n;
var m: number;
}
// Function signature with optional parameter, no type annotation and initializer has initializer's widened type
function opt2(n = { x: null, y: undefined }) {
var m = n;
var m: { x: any; y: any };
}
// Function signature with initializer referencing other parameter to the left
function opt3(n: number, m = n) {
var y = m;
var y: number;
}
// Function signature with optional parameter has correct codegen
// (tested above)
// FunctionExpression with non -void return type annotation return with no expression
function f6(): number {
return;
}
class Derived2 extends Base { private r: string; }
class AnotherClass { private x }
// if f is a contextually typed function expression, the inferred return type is the union type
// of the types of the return statement expressions in the function body,
// ignoring return statements with no expressions.
var f7: (x: number) => string | number = x => { // should be (x: number) => number | string
if (x < 0) { return x; }
return x.toString();
}
var f8: (x: number) => any = x => { // should be (x: number) => Base
return new Base();
return new Derived2();
}
var f9: (x: number) => any = x => { // should be (x: number) => Base
return new Base();
return new Derived();
return new Derived2();
}
var f10: (x: number) => any = x => { // should be (x: number) => Derived | Derived1
return new Derived();
return new Derived2();
}
var f11: (x: number) => any = x => { // should be (x: number) => Base | AnotherClass
return new Base();
return new AnotherClass();
}
var f12: (x: number) => any = x => { // should be (x: number) => Base | AnotherClass
return new Base();
return; // should be ignored
return new AnotherClass();
}

View File

@ -1,10 +1,11 @@
tests/cases/compiler/narrowByEquality.ts(41,5): error TS2839: This condition will always return 'false' since JavaScript compares objects by reference, not value.
tests/cases/compiler/narrowByEquality.ts(54,15): error TS2322: Type 'string | number' is not assignable to type 'number'.
Type 'string' is not assignable to type 'number'.
tests/cases/compiler/narrowByEquality.ts(55,9): error TS2322: Type 'string | number' is not assignable to type 'number'.
Type 'string' is not assignable to type 'number'.
==== tests/cases/compiler/narrowByEquality.ts (2 errors) ====
==== tests/cases/compiler/narrowByEquality.ts (3 errors) ====
declare let x: number | string | boolean
declare let n: number;
declare let s: string;
@ -46,6 +47,8 @@ tests/cases/compiler/narrowByEquality.ts(55,9): error TS2322: Type 'string | num
declare let xAndObj: number | string | boolean | object
if (xAndObj == {}) {
~~~~~~~~~~~~~
!!! error TS2839: This condition will always return 'false' since JavaScript compares objects by reference, not value.
xAndObj;
}

View File

@ -265,6 +265,7 @@ tests/cases/conformance/parser/ecmascript5/parserRealSource7.ts(704,34): error T
tests/cases/conformance/parser/ecmascript5/parserRealSource7.ts(710,69): error TS2304: Cannot find name 'NodeType'.
tests/cases/conformance/parser/ecmascript5/parserRealSource7.ts(710,93): error TS2304: Cannot find name 'FuncDecl'.
tests/cases/conformance/parser/ecmascript5/parserRealSource7.ts(710,136): error TS2304: Cannot find name 'FuncDecl'.
tests/cases/conformance/parser/ecmascript5/parserRealSource7.ts(722,17): error TS2839: This condition will always return 'true' since JavaScript compares objects by reference, not value.
tests/cases/conformance/parser/ecmascript5/parserRealSource7.ts(724,22): error TS2304: Cannot find name 'hasFlag'.
tests/cases/conformance/parser/ecmascript5/parserRealSource7.ts(724,83): error TS2304: Cannot find name 'FncFlags'.
tests/cases/conformance/parser/ecmascript5/parserRealSource7.ts(729,44): error TS2304: Cannot find name 'SymbolKind'.
@ -303,7 +304,7 @@ tests/cases/conformance/parser/ecmascript5/parserRealSource7.ts(827,34): error T
tests/cases/conformance/parser/ecmascript5/parserRealSource7.ts(828,13): error TS2304: Cannot find name 'popTypeCollectionScope'.
==== tests/cases/conformance/parser/ecmascript5/parserRealSource7.ts (303 errors) ====
==== tests/cases/conformance/parser/ecmascript5/parserRealSource7.ts (304 errors) ====
// Copyright (c) Microsoft. All rights reserved. Licensed under the Apache License, Version 2.0.
// See LICENSE.txt in the project root for complete license information.
@ -1562,6 +1563,8 @@ tests/cases/conformance/parser/ecmascript5/parserRealSource7.ts(828,13): error T
fgSym.type &&
fgSym.type.construct &&
fgSym.type.construct.signatures != [] &&
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
!!! error TS2839: This condition will always return 'true' since JavaScript compares objects by reference, not value.
(fgSym.type.construct.signatures[0].declAST == null ||
!hasFlag(fgSym.type.construct.signatures[0].declAST.fncFlags, FncFlags.Ambient)) &&
~~~~~~~

View File

@ -0,0 +1,54 @@
const a = { a: 1 }
const b = [1]
if ({ a: 1 } === { a: 1 }) {
}
if ([1] === [1]) {
}
if (a === { a: 1 }) {
}
if (b === [1]) {
}
if ({ a: 1 } === a) {
}
if ([1] === b) {
}
if ({ a: 1 } !== { a: 1 }) {
}
if ([1] !== [1]) {
}
if (a !== { a: 1 }) {
}
if (b !== [1]) {
}
if ({ a: 1 } !== a) {
}
if ([1] !== b) {
}
if ({ a: 1 } == { a: 1 }) {
}
if ([1] == [1]) {
}
if (a == { a: 1 }) {
}
if (b == [1]) {
}
if ({ a: 1 } == a) {
}
if ([1] == b) {
}
if ({ a: 1 } != { a: 1 }) {
}
if ([1] != [1]) {
}
if (a != { a: 1 }) {
}
if (b != [1]) {
}
if ({ a: 1 } != a) {
}
if ([1] != b) {
}