diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 0acb3a127d5..b9343a2cdbe 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -9513,13 +9513,7 @@ namespace ts { const thisArgumentNode = getThisArgumentOfCall(node); const thisArgumentType = thisArgumentNode ? checkExpression(thisArgumentNode) : voidType; const errorNode = reportErrors ? (thisArgumentNode || node) : undefined; - if (thisArgumentType.flags & TypeFlags.UnionOrIntersection) { - const u = thisArgumentType; - if (!forEach(u.types, t => checkTypeRelatedTo(t, signature.thisType, relation, errorNode, headMessage))) { - return false; - } - } - else if (!checkTypeRelatedTo(thisArgumentType, signature.thisType, relation, errorNode, headMessage)) { + if (!checkTypeRelatedTo(thisArgumentType, signature.thisType, relation, errorNode, headMessage)) { return false; } } diff --git a/src/compiler/core.ts b/src/compiler/core.ts index f1f9d93c5d2..21536da36ff 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -91,23 +91,6 @@ namespace ts { return undefined; } - /** - * Iterates through `array` by index and performs the callback on each element of array until the callback - * returns a falsey value, then returns false. - * If no such value is found, the callback is applied to each element of array and `true` is returned. - */ - export function trueForAll(array: T[], callback: (element: T, index: number) => boolean): boolean { - if (array) { - for (let i = 0, len = array.length; i < len; i++) { - if (!callback(array[i], i)) { - return false; - } - } - } - - return true; - } - export function contains(array: T[], value: T): boolean { if (array) { for (const v of array) { diff --git a/tests/baselines/reference/looseThisTypeInFunctions.errors.txt b/tests/baselines/reference/looseThisTypeInFunctions.errors.txt index 4eef7d83f78..caaf7afb09c 100644 --- a/tests/baselines/reference/looseThisTypeInFunctions.errors.txt +++ b/tests/baselines/reference/looseThisTypeInFunctions.errors.txt @@ -1,13 +1,12 @@ tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(21,1): error TS2322: Type '(this: C, m: number) => number' is not assignable to type '(this: void, m: number) => number'. Types of parameters 'this' and 'this' are incompatible. Type 'void' is not assignable to type 'C'. -tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(32,5): error TS1005: ',' expected. -tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(33,27): error TS2339: Property 'length' does not exist on type 'number'. +tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(33,28): error TS2339: Property 'length' does not exist on type 'number'. tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(37,9): error TS2345: Argument of type 'void' is not assignable to parameter of type 'I'. -tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(46,19): error TS2339: Property 'length' does not exist on type 'number'. +tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(46,20): error TS2339: Property 'length' does not exist on type 'number'. -==== tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts (5 errors) ==== +==== tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts (4 errors) ==== interface I { n: number; explicitThis(this: this, m: number): number; @@ -42,12 +41,10 @@ tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(46,19): error }; let i: I = o; let o2: I = { - n: 1001 + n: 1001, explicitThis: function (m) { - ~~~~~~~~~~~~ -!!! error TS1005: ',' expected. - return m + this.n.length; // error, this.n: number, no member 'length' - ~~~~~~ + return m + this.n.length; // error, this.n: number, no member 'length' + ~~~~~~ !!! error TS2339: Property 'length' does not exist on type 'number'. }, } @@ -63,8 +60,7 @@ tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts(46,19): error o.implicitThis = c.explicitThis; // ok, implicitThis(this:any) is assignable to explicitThis(this: this) o.implicitThis = i.explicitThis; i.explicitThis = function(m) { - return this.n.length; // error, this.n: number - ~~~~~~ + return this.n.length; // error, this.n: number + ~~~~~~ !!! error TS2339: Property 'length' does not exist on type 'number'. - } - \ No newline at end of file + } \ No newline at end of file diff --git a/tests/baselines/reference/looseThisTypeInFunctions.js b/tests/baselines/reference/looseThisTypeInFunctions.js index ecb9f650716..3b172877e0e 100644 --- a/tests/baselines/reference/looseThisTypeInFunctions.js +++ b/tests/baselines/reference/looseThisTypeInFunctions.js @@ -29,9 +29,9 @@ let o = { }; let i: I = o; let o2: I = { - n: 1001 + n: 1001, explicitThis: function (m) { - return m + this.n.length; // error, this.n: number, no member 'length' + return m + this.n.length; // error, this.n: number, no member 'length' }, } let x = i.explicitThis; @@ -44,9 +44,8 @@ o.implicitThis = c.implicitThis; // ok, implicitThis(this:any) o.implicitThis = c.explicitThis; // ok, implicitThis(this:any) is assignable to explicitThis(this: this) o.implicitThis = i.explicitThis; i.explicitThis = function(m) { - return this.n.length; // error, this.n: number -} - + return this.n.length; // error, this.n: number +} //// [looseThisTypeInFunctions.js] var C = (function () { diff --git a/tests/baselines/reference/thisTypeInFunctions.js b/tests/baselines/reference/thisTypeInFunctions.js index af55603a4b7..8d34f9bc2cf 100644 --- a/tests/baselines/reference/thisTypeInFunctions.js +++ b/tests/baselines/reference/thisTypeInFunctions.js @@ -185,11 +185,6 @@ d2.implicit = d1.explicit // ok, 'y' in { x, y } (c assignable to f) b1.implicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) b1.explicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) -// union assignability - -let b1b2: Base1 | Base2; -b1b2.implicit(); - ////// use this-type for construction with new //// function InterfaceThis(this: I) { this.a = 12; @@ -395,9 +390,6 @@ d1.implicit = b2.implicit; // ok, 'y' in D: { x, y } (d assignable e) d2.implicit = d1.explicit; // ok, 'y' in { x, y } (c assignable to f) b1.implicit = d2.implicit; // ok, 'x' and 'y' not in C: { x } (c assignable to f) b1.explicit = d2.implicit; // ok, 'x' and 'y' not in C: { x } (c assignable to f) -// union assignability -var b1b2; -b1b2.implicit(); ////// use this-type for construction with new //// function InterfaceThis() { this.a = 12; diff --git a/tests/baselines/reference/thisTypeInFunctions.symbols b/tests/baselines/reference/thisTypeInFunctions.symbols index 120494c206f..9cd1915fc94 100644 --- a/tests/baselines/reference/thisTypeInFunctions.symbols +++ b/tests/baselines/reference/thisTypeInFunctions.symbols @@ -791,22 +791,10 @@ b1.explicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) >d2 : Symbol(d2, Decl(thisTypeInFunctions.ts, 176, 3)) >implicit : Symbol(Base2.implicit, Decl(thisTypeInFunctions.ts, 166, 13)) -// union assignability - -let b1b2: Base1 | Base2; ->b1b2 : Symbol(b1b2, Decl(thisTypeInFunctions.ts, 188, 3)) ->Base1 : Symbol(Base1, Decl(thisTypeInFunctions.ts, 150, 24)) ->Base2 : Symbol(Base2, Decl(thisTypeInFunctions.ts, 164, 1)) - -b1b2.implicit(); ->b1b2.implicit : Symbol(implicit, Decl(thisTypeInFunctions.ts, 154, 14), Decl(thisTypeInFunctions.ts, 166, 13)) ->b1b2 : Symbol(b1b2, Decl(thisTypeInFunctions.ts, 188, 3)) ->implicit : Symbol(implicit, Decl(thisTypeInFunctions.ts, 154, 14), Decl(thisTypeInFunctions.ts, 166, 13)) - ////// use this-type for construction with new //// function InterfaceThis(this: I) { ->InterfaceThis : Symbol(InterfaceThis, Decl(thisTypeInFunctions.ts, 189, 16)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 192, 23)) +>InterfaceThis : Symbol(InterfaceThis, Decl(thisTypeInFunctions.ts, 184, 25)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 187, 23)) >I : Symbol(I, Decl(thisTypeInFunctions.ts, 22, 21)) this.a = 12; @@ -815,60 +803,60 @@ function InterfaceThis(this: I) { >a : Symbol(I.a, Decl(thisTypeInFunctions.ts, 23, 13)) } function LiteralTypeThis(this: {x: string}) { ->LiteralTypeThis : Symbol(LiteralTypeThis, Decl(thisTypeInFunctions.ts, 194, 1)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 195, 25)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 195, 32)) +>LiteralTypeThis : Symbol(LiteralTypeThis, Decl(thisTypeInFunctions.ts, 189, 1)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 190, 25)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 190, 32)) this.x = "ok"; ->this.x : Symbol(x, Decl(thisTypeInFunctions.ts, 195, 32)) ->this : Symbol(, Decl(thisTypeInFunctions.ts, 195, 30)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 195, 32)) +>this.x : Symbol(x, Decl(thisTypeInFunctions.ts, 190, 32)) +>this : Symbol(, Decl(thisTypeInFunctions.ts, 190, 30)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 190, 32)) } function AnyThis(this: any) { ->AnyThis : Symbol(AnyThis, Decl(thisTypeInFunctions.ts, 197, 1)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 198, 17)) +>AnyThis : Symbol(AnyThis, Decl(thisTypeInFunctions.ts, 192, 1)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 193, 17)) this.x = "ok"; } let interfaceThis = new InterfaceThis(); ->interfaceThis : Symbol(interfaceThis, Decl(thisTypeInFunctions.ts, 201, 3)) ->InterfaceThis : Symbol(InterfaceThis, Decl(thisTypeInFunctions.ts, 189, 16)) +>interfaceThis : Symbol(interfaceThis, Decl(thisTypeInFunctions.ts, 196, 3)) +>InterfaceThis : Symbol(InterfaceThis, Decl(thisTypeInFunctions.ts, 184, 25)) let literalTypeThis = new LiteralTypeThis(); ->literalTypeThis : Symbol(literalTypeThis, Decl(thisTypeInFunctions.ts, 202, 3)) ->LiteralTypeThis : Symbol(LiteralTypeThis, Decl(thisTypeInFunctions.ts, 194, 1)) +>literalTypeThis : Symbol(literalTypeThis, Decl(thisTypeInFunctions.ts, 197, 3)) +>LiteralTypeThis : Symbol(LiteralTypeThis, Decl(thisTypeInFunctions.ts, 189, 1)) let anyThis = new AnyThis(); ->anyThis : Symbol(anyThis, Decl(thisTypeInFunctions.ts, 203, 3)) ->AnyThis : Symbol(AnyThis, Decl(thisTypeInFunctions.ts, 197, 1)) +>anyThis : Symbol(anyThis, Decl(thisTypeInFunctions.ts, 198, 3)) +>AnyThis : Symbol(AnyThis, Decl(thisTypeInFunctions.ts, 192, 1)) //// type parameter inference //// declare var f: { ->f : Symbol(f, Decl(thisTypeInFunctions.ts, 206, 11)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 201, 11)) (this: void, x: number): number, ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 207, 5)) ->x : Symbol(x, Decl(thisTypeInFunctions.ts, 207, 16)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 202, 5)) +>x : Symbol(x, Decl(thisTypeInFunctions.ts, 202, 16)) call(this: (...argArray: any[]) => U, ...argArray: any[]): U; ->call : Symbol(call, Decl(thisTypeInFunctions.ts, 207, 36)) ->U : Symbol(U, Decl(thisTypeInFunctions.ts, 208, 9)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 208, 12)) ->argArray : Symbol(argArray, Decl(thisTypeInFunctions.ts, 208, 19)) ->U : Symbol(U, Decl(thisTypeInFunctions.ts, 208, 9)) ->argArray : Symbol(argArray, Decl(thisTypeInFunctions.ts, 208, 44)) ->U : Symbol(U, Decl(thisTypeInFunctions.ts, 208, 9)) +>call : Symbol(call, Decl(thisTypeInFunctions.ts, 202, 36)) +>U : Symbol(U, Decl(thisTypeInFunctions.ts, 203, 9)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 203, 12)) +>argArray : Symbol(argArray, Decl(thisTypeInFunctions.ts, 203, 19)) +>U : Symbol(U, Decl(thisTypeInFunctions.ts, 203, 9)) +>argArray : Symbol(argArray, Decl(thisTypeInFunctions.ts, 203, 44)) +>U : Symbol(U, Decl(thisTypeInFunctions.ts, 203, 9)) }; let n: number = f.call(12); ->n : Symbol(n, Decl(thisTypeInFunctions.ts, 210, 3)) ->f.call : Symbol(call, Decl(thisTypeInFunctions.ts, 207, 36)) ->f : Symbol(f, Decl(thisTypeInFunctions.ts, 206, 11)) ->call : Symbol(call, Decl(thisTypeInFunctions.ts, 207, 36)) +>n : Symbol(n, Decl(thisTypeInFunctions.ts, 205, 3)) +>f.call : Symbol(call, Decl(thisTypeInFunctions.ts, 202, 36)) +>f : Symbol(f, Decl(thisTypeInFunctions.ts, 201, 11)) +>call : Symbol(call, Decl(thisTypeInFunctions.ts, 202, 36)) function missingTypeIsImplicitAny(this, a: number) { return a; } ->missingTypeIsImplicitAny : Symbol(missingTypeIsImplicitAny, Decl(thisTypeInFunctions.ts, 210, 27)) ->this : Symbol(this, Decl(thisTypeInFunctions.ts, 212, 34)) ->a : Symbol(a, Decl(thisTypeInFunctions.ts, 212, 39)) ->a : Symbol(a, Decl(thisTypeInFunctions.ts, 212, 39)) +>missingTypeIsImplicitAny : Symbol(missingTypeIsImplicitAny, Decl(thisTypeInFunctions.ts, 205, 27)) +>this : Symbol(this, Decl(thisTypeInFunctions.ts, 207, 34)) +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 207, 39)) +>a : Symbol(a, Decl(thisTypeInFunctions.ts, 207, 39)) diff --git a/tests/baselines/reference/thisTypeInFunctions.types b/tests/baselines/reference/thisTypeInFunctions.types index e5f6a561d59..3922e454c3f 100644 --- a/tests/baselines/reference/thisTypeInFunctions.types +++ b/tests/baselines/reference/thisTypeInFunctions.types @@ -952,19 +952,6 @@ b1.explicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) >d2 : Derived2 >implicit : (this: Derived2) => number -// union assignability - -let b1b2: Base1 | Base2; ->b1b2 : Base1 | Base2 ->Base1 : Base1 ->Base2 : Base2 - -b1b2.implicit(); ->b1b2.implicit() : number ->b1b2.implicit : ((this: Base1) => number) | ((this: Base2) => number) ->b1b2 : Base1 | Base2 ->implicit : ((this: Base1) => number) | ((this: Base2) => number) - ////// use this-type for construction with new //// function InterfaceThis(this: I) { >InterfaceThis : (this: I) => void diff --git a/tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts b/tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts index 3e8bdb11170..b151961e324 100644 --- a/tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts +++ b/tests/cases/conformance/types/thisType/looseThisTypeInFunctions.ts @@ -28,9 +28,9 @@ let o = { }; let i: I = o; let o2: I = { - n: 1001 + n: 1001, explicitThis: function (m) { - return m + this.n.length; // error, this.n: number, no member 'length' + return m + this.n.length; // error, this.n: number, no member 'length' }, } let x = i.explicitThis; @@ -43,5 +43,5 @@ o.implicitThis = c.implicitThis; // ok, implicitThis(this:any) o.implicitThis = c.explicitThis; // ok, implicitThis(this:any) is assignable to explicitThis(this: this) o.implicitThis = i.explicitThis; i.explicitThis = function(m) { - return this.n.length; // error, this.n: number -} + return this.n.length; // error, this.n: number +} \ No newline at end of file diff --git a/tests/cases/conformance/types/thisType/thisTypeInFuncTemp.ts b/tests/cases/conformance/types/thisType/thisTypeInFuncTemp.ts index 2f4873031fb..e4ae3deb171 100644 --- a/tests/cases/conformance/types/thisType/thisTypeInFuncTemp.ts +++ b/tests/cases/conformance/types/thisType/thisTypeInFuncTemp.ts @@ -1,27 +1,9 @@ -// @strictThis: true -// 1. contextual typing predicate is wrong (currently: method2: function () ...) -// () -> yes (allParametersAreUntyped=t, noThisParameter=t, noTypeParameters=t) -// ok .. fixed? -// 2. contextual typing of this doesn't seem to work -// strictThis was turned off. DUH. -// 3. when it DID work, it was giving bogus types with strictThis OFF (see the last example) -interface T { - (x: number): void; -} -interface I { - n: number - method(this: this): number; - method2(this: this): number; -} -let i: I = { - n: 12, - method: function(this) { // this: I - return this.n.length; // error, 'number' has no property 'length' - }, - method2: function() { // this: I - return this.n.length; // error, 'number' has no property 'length' - } -} -i.method = function () { return this.n.length } // this: I -i.method = function (this) { return this.n.length } // this: I -var t: T = function (this, y) { } // yes! (but this: any NOT number!!) \ No newline at end of file +//@strictThis: true +interface A { a: number; m(this: this): number } +interface B { b: number, m(this: this): number } +interface C { c: number; m(): number } +let a: A; +let ab: A | B; +let abc: A | B | C; +// ab.m().length; +abc.m().length; // should be OK? this: any, right? \ No newline at end of file diff --git a/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts b/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts index e5cc9e45ba2..8676d12c5ab 100644 --- a/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts +++ b/tests/cases/conformance/types/thisType/thisTypeInFunctions.ts @@ -185,11 +185,6 @@ d2.implicit = d1.explicit // ok, 'y' in { x, y } (c assignable to f) b1.implicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) b1.explicit = d2.implicit // ok, 'x' and 'y' not in C: { x } (c assignable to f) -// union assignability - -let b1b2: Base1 | Base2; -b1b2.implicit(); - ////// use this-type for construction with new //// function InterfaceThis(this: I) { this.a = 12;