Use correct this in tuple type parameter constraints

Instantiate this in tuple types used as type parameter constraints
This commit is contained in:
Nathan Shively-Sanders 2016-08-09 12:44:08 -07:00
parent 3f1ec7ad4b
commit 7e115bbbef
5 changed files with 190 additions and 2 deletions

View file

@ -4000,6 +4000,10 @@ namespace ts {
return createTypeReference((<TypeReference>type).target,
concatenate((<TypeReference>type).typeArguments, [thisArgument || (<TypeReference>type).target.thisType]));
}
if (type.flags & TypeFlags.Tuple) {
resolveTupleTypeMembers(type as TupleType, thisArgument);
return type;
}
return type;
}
@ -4100,10 +4104,10 @@ namespace ts {
return members;
}
function resolveTupleTypeMembers(type: TupleType) {
function resolveTupleTypeMembers(type: TupleType, thisArgument?: Type) {
const arrayElementType = getUnionType(type.elementTypes);
// Make the tuple type itself the 'this' type by including an extra type argument
const arrayType = resolveStructuredTypeMembers(createTypeFromGenericGlobalType(globalArrayType, [arrayElementType, type]));
const arrayType = resolveStructuredTypeMembers(createTypeFromGenericGlobalType(globalArrayType, [arrayElementType, thisArgument || type]));
const members = createTupleTypeMemberSymbols(type.elementTypes);
addInheritedMembers(members, arrayType.properties);
setObjectTypeMembers(type, members, arrayType.callSignatures, arrayType.constructSignatures, arrayType.stringIndexInfo, arrayType.numberIndexInfo);

View file

@ -0,0 +1,29 @@
//// [thisInTupleTypeParameterConstraints.ts]
/// <reference no-default-lib="true"/>
interface Boolean {}
interface IArguments {}
interface Function {}
interface Number {}
interface RegExp {}
interface Object {}
interface String {}
interface Array<T> {
// 4 methods will run out of memory if this-types are not instantiated
// correctly for tuple types that are type parameter constraints
map<U>(arg: this): void;
reduceRight<U>(arg: this): void;
reduce<U>(arg: this): void;
reduce2<U>(arg: this): void;
}
declare function f<T extends [(x: number) => number]>(a: T): void;
let x: [(x: number) => number];
f(x);
//// [thisInTupleTypeParameterConstraints.js]
/// <reference no-default-lib="true"/>
var x;
f(x);

View file

@ -0,0 +1,66 @@
=== tests/cases/compiler/thisInTupleTypeParameterConstraints.ts ===
/// <reference no-default-lib="true"/>
interface Boolean {}
>Boolean : Symbol(Boolean, Decl(thisInTupleTypeParameterConstraints.ts, 0, 0))
interface IArguments {}
>IArguments : Symbol(IArguments, Decl(thisInTupleTypeParameterConstraints.ts, 2, 20))
interface Function {}
>Function : Symbol(Function, Decl(thisInTupleTypeParameterConstraints.ts, 3, 23))
interface Number {}
>Number : Symbol(Number, Decl(thisInTupleTypeParameterConstraints.ts, 4, 21))
interface RegExp {}
>RegExp : Symbol(RegExp, Decl(thisInTupleTypeParameterConstraints.ts, 5, 19))
interface Object {}
>Object : Symbol(Object, Decl(thisInTupleTypeParameterConstraints.ts, 6, 19))
interface String {}
>String : Symbol(String, Decl(thisInTupleTypeParameterConstraints.ts, 7, 19))
interface Array<T> {
>Array : Symbol(Array, Decl(thisInTupleTypeParameterConstraints.ts, 8, 19))
>T : Symbol(T, Decl(thisInTupleTypeParameterConstraints.ts, 10, 16))
// 4 methods will run out of memory if this-types are not instantiated
// correctly for tuple types that are type parameter constraints
map<U>(arg: this): void;
>map : Symbol(Array.map, Decl(thisInTupleTypeParameterConstraints.ts, 10, 20))
>U : Symbol(U, Decl(thisInTupleTypeParameterConstraints.ts, 13, 8))
>arg : Symbol(arg, Decl(thisInTupleTypeParameterConstraints.ts, 13, 11))
reduceRight<U>(arg: this): void;
>reduceRight : Symbol(Array.reduceRight, Decl(thisInTupleTypeParameterConstraints.ts, 13, 28))
>U : Symbol(U, Decl(thisInTupleTypeParameterConstraints.ts, 14, 16))
>arg : Symbol(arg, Decl(thisInTupleTypeParameterConstraints.ts, 14, 19))
reduce<U>(arg: this): void;
>reduce : Symbol(Array.reduce, Decl(thisInTupleTypeParameterConstraints.ts, 14, 36))
>U : Symbol(U, Decl(thisInTupleTypeParameterConstraints.ts, 15, 11))
>arg : Symbol(arg, Decl(thisInTupleTypeParameterConstraints.ts, 15, 14))
reduce2<U>(arg: this): void;
>reduce2 : Symbol(Array.reduce2, Decl(thisInTupleTypeParameterConstraints.ts, 15, 31))
>U : Symbol(U, Decl(thisInTupleTypeParameterConstraints.ts, 16, 12))
>arg : Symbol(arg, Decl(thisInTupleTypeParameterConstraints.ts, 16, 15))
}
declare function f<T extends [(x: number) => number]>(a: T): void;
>f : Symbol(f, Decl(thisInTupleTypeParameterConstraints.ts, 17, 1))
>T : Symbol(T, Decl(thisInTupleTypeParameterConstraints.ts, 19, 19))
>x : Symbol(x, Decl(thisInTupleTypeParameterConstraints.ts, 19, 31))
>a : Symbol(a, Decl(thisInTupleTypeParameterConstraints.ts, 19, 54))
>T : Symbol(T, Decl(thisInTupleTypeParameterConstraints.ts, 19, 19))
let x: [(x: number) => number];
>x : Symbol(x, Decl(thisInTupleTypeParameterConstraints.ts, 20, 3))
>x : Symbol(x, Decl(thisInTupleTypeParameterConstraints.ts, 20, 9))
f(x);
>f : Symbol(f, Decl(thisInTupleTypeParameterConstraints.ts, 17, 1))
>x : Symbol(x, Decl(thisInTupleTypeParameterConstraints.ts, 20, 3))

View file

@ -0,0 +1,67 @@
=== tests/cases/compiler/thisInTupleTypeParameterConstraints.ts ===
/// <reference no-default-lib="true"/>
interface Boolean {}
>Boolean : Boolean
interface IArguments {}
>IArguments : IArguments
interface Function {}
>Function : Function
interface Number {}
>Number : Number
interface RegExp {}
>RegExp : RegExp
interface Object {}
>Object : Object
interface String {}
>String : String
interface Array<T> {
>Array : T[]
>T : T
// 4 methods will run out of memory if this-types are not instantiated
// correctly for tuple types that are type parameter constraints
map<U>(arg: this): void;
>map : <U>(arg: this) => void
>U : U
>arg : this
reduceRight<U>(arg: this): void;
>reduceRight : <U>(arg: this) => void
>U : U
>arg : this
reduce<U>(arg: this): void;
>reduce : <U>(arg: this) => void
>U : U
>arg : this
reduce2<U>(arg: this): void;
>reduce2 : <U>(arg: this) => void
>U : U
>arg : this
}
declare function f<T extends [(x: number) => number]>(a: T): void;
>f : <T extends [(x: number) => number]>(a: T) => void
>T : T
>x : number
>a : T
>T : T
let x: [(x: number) => number];
>x : [(x: number) => number]
>x : number
f(x);
>f(x) : void
>f : <T extends [(x: number) => number]>(a: T) => void
>x : [(x: number) => number]

View file

@ -0,0 +1,22 @@
/// <reference no-default-lib="true"/>
interface Boolean {}
interface IArguments {}
interface Function {}
interface Number {}
interface RegExp {}
interface Object {}
interface String {}
interface Array<T> {
// 4 methods will run out of memory if this-types are not instantiated
// correctly for tuple types that are type parameter constraints
map<U>(arg: this): void;
reduceRight<U>(arg: this): void;
reduce<U>(arg: this): void;
reduce2<U>(arg: this): void;
}
declare function f<T extends [(x: number) => number]>(a: T): void;
let x: [(x: number) => number];
f(x);