Skip to content

Commit cd05c07

Browse files
committed
Add comment explaining type alias instantiation strategy
1 parent 6ceab7b commit cd05c07

File tree

1 file changed

+17
-0
lines changed

1 file changed

+17
-0
lines changed

src/compiler/checker.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6519,6 +6519,23 @@ namespace ts {
65196519

65206520
function instantiateType(type: Type, mapper: TypeMapper): Type {
65216521
if (type && mapper !== identityMapper) {
6522+
// If we are instantiating a type that has a top-level type alias, obtain the instantiation through
6523+
// the type alias instead in order to share instantiations for the same type arguments. This can
6524+
// dramatically reduce the number of structurally identical types we generate. Note that we can only
6525+
// perform this optimization for top-level type aliases. Consider:
6526+
//
6527+
// function f1<T>(x: T) {
6528+
// type Foo<X> = { x: X, t: T };
6529+
// let obj: Foo<T> = { x: x };
6530+
// return obj;
6531+
// }
6532+
// function f2<U>(x: U) { return f1(x); }
6533+
// let z = f2(42);
6534+
//
6535+
// Above, the declaration of f2 has an inferred return type that is an instantiation of f1's Foo<X>
6536+
// equivalent to { x: U, t: U }. When instantiating this return type, we can't go back to Foo<X>'s
6537+
// cache because all cached instantiations are of the form { x: ???, t: T }, i.e. they have not been
6538+
// instantiated for T. Instead, we need to further instantiate the { x: U, t: U } form.
65226539
if (type.aliasSymbol && isTopLevelTypeAlias(type.aliasSymbol)) {
65236540
if (type.aliasTypeArguments) {
65246541
return getTypeAliasInstantiation(type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper));

0 commit comments

Comments
 (0)