mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-16 05:58:32 -06:00
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:
parent
738713b146
commit
41bb446865
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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'.
|
||||
}
|
||||
|
||||
}
|
||||
@ -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 () {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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))
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
}
|
||||
@ -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?
|
||||
@ -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;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user