Retain substitution types through instantiation if possible (#30059)

This commit is contained in:
Wesley Wigham 2019-02-25 17:10:03 -08:00 committed by GitHub
parent 0e858a6e16
commit c5061486a9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 200 additions and 1 deletions

View file

@ -11062,7 +11062,13 @@ namespace ts {
return getConditionalTypeInstantiation(<ConditionalType>type, combineTypeMappers((<ConditionalType>type).mapper, mapper));
}
if (flags & TypeFlags.Substitution) {
return instantiateType((<SubstitutionType>type).typeVariable, mapper);
const maybeVariable = instantiateType((<SubstitutionType>type).typeVariable, mapper);
if (maybeVariable.flags & TypeFlags.TypeVariable) {
return getSubstitutionType(maybeVariable as TypeVariable, instantiateType((<SubstitutionType>type).substitute, mapper));
}
else {
return maybeVariable;
}
}
return type;
}
@ -14465,6 +14471,9 @@ namespace ts {
}
}
}
else if (target.flags & TypeFlags.Substitution) {
inferFromTypes(source, (target as SubstitutionType).typeVariable);
}
if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (<TypeReference>source).target === (<TypeReference>target).target) {
// If source and target are references to the same generic type, infer from type arguments
const sourceTypes = (<TypeReference>source).typeArguments || emptyArray;

View file

@ -0,0 +1,36 @@
//// [inlinedAliasAssignableToConstraintSameAsAlias.ts]
interface RelationFields {
x: A;
y: A[];
z: A[];
}
type Name = keyof RelationFields;
type ShouldA<RF extends RelationFields, N extends Name> = RF[N] extends A[]
? RF[N][0]
: never;
class A {
x: A;
y: A[];
z: A[];
whereRelated< // Works // Type is same as A1, but is not assignable to type A
RF extends RelationFields = RelationFields,
N extends Name = Name,
A1 extends A = RF[N] extends A[] ? RF[N][0] : never,
A2 extends A = ShouldA<RF, N>
>(): number {
return 1;
}
}
//// [inlinedAliasAssignableToConstraintSameAsAlias.js]
var A = /** @class */ (function () {
function A() {
}
A.prototype.whereRelated = function () {
return 1;
};
return A;
}());

View file

@ -0,0 +1,85 @@
=== tests/cases/compiler/inlinedAliasAssignableToConstraintSameAsAlias.ts ===
interface RelationFields {
>RelationFields : Symbol(RelationFields, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 0, 0))
x: A;
>x : Symbol(RelationFields.x, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 0, 26))
>A : Symbol(A, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 8, 10))
y: A[];
>y : Symbol(RelationFields.y, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 1, 7))
>A : Symbol(A, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 8, 10))
z: A[];
>z : Symbol(RelationFields.z, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 2, 9))
>A : Symbol(A, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 8, 10))
}
type Name = keyof RelationFields;
>Name : Symbol(Name, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 4, 1))
>RelationFields : Symbol(RelationFields, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 0, 0))
type ShouldA<RF extends RelationFields, N extends Name> = RF[N] extends A[]
>ShouldA : Symbol(ShouldA, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 5, 33))
>RF : Symbol(RF, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 6, 13))
>RelationFields : Symbol(RelationFields, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 0, 0))
>N : Symbol(N, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 6, 39))
>Name : Symbol(Name, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 4, 1))
>RF : Symbol(RF, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 6, 13))
>N : Symbol(N, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 6, 39))
>A : Symbol(A, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 8, 10))
? RF[N][0]
>RF : Symbol(RF, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 6, 13))
>N : Symbol(N, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 6, 39))
: never;
class A {
>A : Symbol(A, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 8, 10))
x: A;
>x : Symbol(A.x, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 10, 9))
>A : Symbol(A, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 8, 10))
y: A[];
>y : Symbol(A.y, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 11, 7))
>A : Symbol(A, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 8, 10))
z: A[];
>z : Symbol(A.z, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 12, 9))
>A : Symbol(A, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 8, 10))
whereRelated< // Works // Type is same as A1, but is not assignable to type A
>whereRelated : Symbol(A.whereRelated, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 13, 9))
RF extends RelationFields = RelationFields,
>RF : Symbol(RF, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 15, 15))
>RelationFields : Symbol(RelationFields, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 0, 0))
>RelationFields : Symbol(RelationFields, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 0, 0))
N extends Name = Name,
>N : Symbol(N, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 16, 47))
>Name : Symbol(Name, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 4, 1))
>Name : Symbol(Name, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 4, 1))
A1 extends A = RF[N] extends A[] ? RF[N][0] : never,
>A1 : Symbol(A1, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 17, 26))
>A : Symbol(A, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 8, 10))
>RF : Symbol(RF, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 15, 15))
>N : Symbol(N, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 16, 47))
>A : Symbol(A, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 8, 10))
>RF : Symbol(RF, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 15, 15))
>N : Symbol(N, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 16, 47))
A2 extends A = ShouldA<RF, N>
>A2 : Symbol(A2, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 18, 56))
>A : Symbol(A, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 8, 10))
>ShouldA : Symbol(ShouldA, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 5, 33))
>RF : Symbol(RF, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 15, 15))
>N : Symbol(N, Decl(inlinedAliasAssignableToConstraintSameAsAlias.ts, 16, 47))
>(): number {
return 1;
}
}

View file

@ -0,0 +1,45 @@
=== tests/cases/compiler/inlinedAliasAssignableToConstraintSameAsAlias.ts ===
interface RelationFields {
x: A;
>x : A
y: A[];
>y : A[]
z: A[];
>z : A[]
}
type Name = keyof RelationFields;
>Name : "x" | "y" | "z"
type ShouldA<RF extends RelationFields, N extends Name> = RF[N] extends A[]
>ShouldA : ShouldA<RF, N>
? RF[N][0]
: never;
class A {
>A : A
x: A;
>x : A
y: A[];
>y : A[]
z: A[];
>z : A[]
whereRelated< // Works // Type is same as A1, but is not assignable to type A
>whereRelated : <RF extends RelationFields = RelationFields, N extends "x" | "y" | "z" = "x" | "y" | "z", A1 extends A = RF[N] extends A[] ? RF[N][0] : never, A2 extends A = ShouldA<RF, N>>() => number
RF extends RelationFields = RelationFields,
N extends Name = Name,
A1 extends A = RF[N] extends A[] ? RF[N][0] : never,
A2 extends A = ShouldA<RF, N>
>(): number {
return 1;
>1 : 1
}
}

View file

@ -0,0 +1,24 @@
interface RelationFields {
x: A;
y: A[];
z: A[];
}
type Name = keyof RelationFields;
type ShouldA<RF extends RelationFields, N extends Name> = RF[N] extends A[]
? RF[N][0]
: never;
class A {
x: A;
y: A[];
z: A[];
whereRelated< // Works // Type is same as A1, but is not assignable to type A
RF extends RelationFields = RelationFields,
N extends Name = Name,
A1 extends A = RF[N] extends A[] ? RF[N][0] : never,
A2 extends A = ShouldA<RF, N>
>(): number {
return 1;
}
}