Erase substitution types in type references and type alias instantiations

This commit is contained in:
Anders Hejlsberg
2018-01-16 12:51:24 -08:00
parent 9598acd477
commit e96ec8c2c7
2 changed files with 14 additions and 0 deletions
+10
View File
@@ -7316,7 +7316,16 @@ namespace ts {
return result & TypeFlags.PropagatingFlags;
}
// This function replaces substitution types in the given array with their underlying type parameter.
// We do this when creating type references and type alias instantiations because subsitution types are
// no longer necessary once the type arguments have been validated against their corresponding type
// parameter constraints.
function eraseSubstitutionTypes(types: Type[]) {
return sameMap(types, t => t.flags & TypeFlags.Substitution ? (<SubstitutionType>t).typeParameter : t);
}
function createTypeReference(target: GenericType, typeArguments: Type[]): TypeReference {
typeArguments = eraseSubstitutionTypes(typeArguments);
const id = getTypeListId(typeArguments);
let type = target.instantiations.get(id);
if (!type) {
@@ -7383,6 +7392,7 @@ namespace ts {
}
function getTypeAliasInstantiation(symbol: Symbol, typeArguments: Type[]): Type {
typeArguments = eraseSubstitutionTypes(typeArguments);
const type = getDeclaredTypeOfSymbol(symbol);
const links = getSymbolLinks(symbol);
const typeParameters = links.typeParameters;
+4
View File
@@ -3703,6 +3703,10 @@ namespace ts {
}
// Type parameter substitution (TypeFlags.Substitution)
// Substitution types are created for type parameter references that occur in the true branch
// of a conditional type. For example, in 'T extends string ? Foo<T> : Bar<T>', the reference to
// T in Foo<T> is resolved as a substitution type that substitutes 'string & T' for T. Thus, if
// Foo<T> has a 'string' constraint on its type parameter, T will satisfy it.
export interface SubstitutionType extends InstantiableType {
typeParameter: TypeParameter; // Target type parameter
substitute: Type; // Type to substitute for type parameter