Revert unioning of this argument types

The right solution is to not instantiate this-types of unions, which is a
separate problem more to do with this-class types.
This commit is contained in:
Nathan Shively-Sanders 2016-02-08 16:39:19 -08:00
parent 738713b146
commit 41bb446865
10 changed files with 61 additions and 145 deletions

View File

@ -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 = <UnionType>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;
}
}

View File

@ -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<T>(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<T>(array: T[], value: T): boolean {
if (array) {
for (const v of array) {

View File

@ -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'.
}
}

View File

@ -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 () {

View File

@ -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;

View File

@ -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<U>(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))

View File

@ -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

View File

@ -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
}

View File

@ -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!!)
//@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?

View File

@ -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;