Merge pull request #10234 from Microsoft/correct-this-in-tuple-type-parameter-constraints

Correct this in tuple type parameter constraints
This commit is contained in:
Nathan Shively-Sanders 2016-08-11 09:44:50 -07:00 committed by GitHub
commit 688e9bc455
6 changed files with 196 additions and 6 deletions

View file

@ -1538,8 +1538,8 @@ namespace ts {
function createType(flags: TypeFlags): Type {
const result = new Type(checker, flags);
result.id = typeCount;
typeCount++;
result.id = typeCount;
return result;
}
@ -4000,6 +4000,9 @@ namespace ts {
return createTypeReference((<TypeReference>type).target,
concatenate((<TypeReference>type).typeArguments, [thisArgument || (<TypeReference>type).target.thisType]));
}
if (type.flags & TypeFlags.Tuple) {
return createTupleType((type as TupleType).elementTypes, thisArgument);
}
return type;
}
@ -4103,7 +4106,8 @@ namespace ts {
function resolveTupleTypeMembers(type: TupleType) {
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]));
// (Unless it's provided in the case that the tuple is a type parameter constraint)
const arrayType = resolveStructuredTypeMembers(createTypeFromGenericGlobalType(globalArrayType, [arrayElementType, type.thisType || type]));
const members = createTupleTypeMemberSymbols(type.elementTypes);
addInheritedMembers(members, arrayType.properties);
setObjectTypeMembers(type, members, arrayType.callSignatures, arrayType.constructSignatures, arrayType.stringIndexInfo, arrayType.numberIndexInfo);
@ -5230,15 +5234,16 @@ namespace ts {
return links.resolvedType;
}
function createTupleType(elementTypes: Type[]) {
const id = getTypeListId(elementTypes);
return tupleTypes[id] || (tupleTypes[id] = createNewTupleType(elementTypes));
function createTupleType(elementTypes: Type[], thisType?: Type) {
const id = getTypeListId(elementTypes) + "," + (thisType ? thisType.id : 0);
return tupleTypes[id] || (tupleTypes[id] = createNewTupleType(elementTypes, thisType));
}
function createNewTupleType(elementTypes: Type[]) {
function createNewTupleType(elementTypes: Type[], thisType?: Type) {
const propagatedFlags = getPropagatingFlagsOfTypes(elementTypes, /*excludeKinds*/ 0);
const type = <TupleType>createObjectType(TypeFlags.Tuple | propagatedFlags);
type.elementTypes = elementTypes;
type.thisType = thisType;
return type;
}

View file

@ -2371,6 +2371,7 @@ namespace ts {
export interface TupleType extends ObjectType {
elementTypes: Type[]; // Element types
thisType?: Type; // This-type of tuple (only needed for tuples that are constraints of type parameters)
}
export interface UnionOrIntersectionType extends Type {

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