Merge pull request #12068 from Microsoft/fixTypeAliasDisplay

Fix type alias display
This commit is contained in:
Anders Hejlsberg 2016-11-08 06:43:38 -08:00 committed by GitHub
commit 2282477012
8 changed files with 204 additions and 23 deletions

View file

@ -2229,14 +2229,8 @@ namespace ts {
// The specified symbol flags need to be reinterpreted as type flags
buildSymbolDisplay(type.symbol, writer, enclosingDeclaration, SymbolFlags.Type, SymbolFormatFlags.None, nextFlags);
}
else if (!(flags & TypeFormatFlags.InTypeAlias) && ((getObjectFlags(type) & ObjectFlags.Anonymous && !(<AnonymousType>type).target) || type.flags & TypeFlags.UnionOrIntersection) && type.aliasSymbol &&
else if (!(flags & TypeFormatFlags.InTypeAlias) && (getObjectFlags(type) & ObjectFlags.Anonymous || type.flags & TypeFlags.UnionOrIntersection) && type.aliasSymbol &&
isSymbolAccessible(type.aliasSymbol, enclosingDeclaration, SymbolFlags.Type, /*shouldComputeAliasesToMakeVisible*/ false).accessibility === SymbolAccessibility.Accessible) {
// We emit inferred type as type-alias at the current localtion if all the following is true
// the input type is has alias symbol that is accessible
// the input type is a union, intersection or anonymous type that is fully instantiated (if not we want to keep dive into)
// e.g.: export type Bar<X, Y> = () => [X, Y];
// export type Foo<Y> = Bar<any, Y>;
// export const y = (x: Foo<string>) => 1 // we want to emit as ...x: () => [any, string])
const typeArguments = type.aliasTypeArguments;
writeSymbolTypeReference(type.aliasSymbol, typeArguments, 0, typeArguments ? typeArguments.length : 0, nextFlags);
}
@ -4164,8 +4158,8 @@ namespace ts {
else {
mapper = createTypeMapper(typeParameters, typeArguments);
members = createInstantiatedSymbolTable(source.declaredProperties, mapper, /*mappingThisOnly*/ typeParameters.length === 1);
callSignatures = instantiateList(source.declaredCallSignatures, mapper, instantiateSignature);
constructSignatures = instantiateList(source.declaredConstructSignatures, mapper, instantiateSignature);
callSignatures = instantiateSignatures(source.declaredCallSignatures, mapper);
constructSignatures = instantiateSignatures(source.declaredConstructSignatures, mapper);
stringIndexInfo = instantiateIndexInfo(source.declaredStringIndexInfo, mapper);
numberIndexInfo = instantiateIndexInfo(source.declaredNumberIndexInfo, mapper);
}
@ -4363,8 +4357,8 @@ namespace ts {
const symbol = type.symbol;
if (type.target) {
const members = createInstantiatedSymbolTable(getPropertiesOfObjectType(type.target), type.mapper, /*mappingThisOnly*/ false);
const callSignatures = instantiateList(getSignaturesOfType(type.target, SignatureKind.Call), type.mapper, instantiateSignature);
const constructSignatures = instantiateList(getSignaturesOfType(type.target, SignatureKind.Construct), type.mapper, instantiateSignature);
const callSignatures = instantiateSignatures(getSignaturesOfType(type.target, SignatureKind.Call), type.mapper);
const constructSignatures = instantiateSignatures(getSignaturesOfType(type.target, SignatureKind.Construct), type.mapper);
const stringIndexInfo = instantiateIndexInfo(getIndexInfoOfType(type.target, IndexKind.String), type.mapper);
const numberIndexInfo = instantiateIndexInfo(getIndexInfoOfType(type.target, IndexKind.Number), type.mapper);
setStructuredTypeMembers(type, members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo);
@ -6043,6 +6037,14 @@ namespace ts {
return items;
}
function instantiateTypes(types: Type[], mapper: TypeMapper) {
return instantiateList(types, mapper, instantiateType);
}
function instantiateSignatures(signatures: Signature[], mapper: TypeMapper) {
return instantiateList(signatures, mapper, instantiateSignature);
}
function createUnaryTypeMapper(source: Type, target: Type): TypeMapper {
return t => t === source ? target : t;
}
@ -6069,7 +6071,6 @@ namespace ts {
count == 2 ? createBinaryTypeMapper(sources[0], targets ? targets[0] : anyType, sources[1], targets ? targets[1] : anyType) :
createArrayTypeMapper(sources, targets);
mapper.mappedTypes = sources;
mapper.targetTypes = targets;
return mapper;
}
@ -6196,7 +6197,7 @@ namespace ts {
result.target = type;
result.mapper = mapper;
result.aliasSymbol = type.aliasSymbol;
result.aliasTypeArguments = mapper.targetTypes;
result.aliasTypeArguments = instantiateTypes(type.aliasTypeArguments, mapper);
mapper.instantiations[type.id] = result;
return result;
}
@ -6272,14 +6273,14 @@ namespace ts {
instantiateAnonymousType(<AnonymousType>type, mapper) : type;
}
if ((<ObjectType>type).objectFlags & ObjectFlags.Reference) {
return createTypeReference((<TypeReference>type).target, instantiateList((<TypeReference>type).typeArguments, mapper, instantiateType));
return createTypeReference((<TypeReference>type).target, instantiateTypes((<TypeReference>type).typeArguments, mapper));
}
}
if (type.flags & TypeFlags.Union && !(type.flags & TypeFlags.Primitive)) {
return getUnionType(instantiateList((<UnionType>type).types, mapper, instantiateType), /*subtypeReduction*/ false, type.aliasSymbol, mapper.targetTypes);
return getUnionType(instantiateTypes((<UnionType>type).types, mapper), /*subtypeReduction*/ false, type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper));
}
if (type.flags & TypeFlags.Intersection) {
return getIntersectionType(instantiateList((<IntersectionType>type).types, mapper, instantiateType), type.aliasSymbol, mapper.targetTypes);
return getIntersectionType(instantiateTypes((<IntersectionType>type).types, mapper), type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper));
}
if (type.flags & TypeFlags.Index) {
return getIndexType(instantiateType((<IndexType>type).type, mapper));

View file

@ -2943,7 +2943,6 @@ namespace ts {
export interface TypeMapper {
(t: TypeParameter): Type;
mappedTypes?: Type[]; // Types mapped by this mapper
targetTypes?: Type[]; // Types substituted for mapped types
instantiations?: Type[]; // Cache of instantiations created using this type mapper.
context?: InferenceContext; // The inference context this mapper was created from.
// Only inference mappers have this set (in createInferenceMapper).

View file

@ -12,4 +12,4 @@ exports.y = function (x) { return 1; };
//// [declarationEmitTypeAliasWithTypeParameters1.d.ts]
export declare type Bar<X, Y> = () => [X, Y];
export declare type Foo<Y> = Bar<any, Y>;
export declare const y: (x: () => [any, string]) => number;
export declare const y: (x: Bar<any, string>) => number;

View file

@ -8,15 +8,15 @@ export type Bar<X, Y> = () => [X, Y];
>Y : Y
export type Foo<Y> = Bar<any, Y>;
>Foo : () => [any, Y]
>Foo : Bar<any, Y>
>Y : Y
>Bar : Bar<X, Y>
>Y : Y
export const y = (x: Foo<string>) => 1
>y : (x: () => [any, string]) => number
>(x: Foo<string>) => 1 : (x: () => [any, string]) => number
>x : () => [any, string]
>Foo : () => [any, Y]
>y : (x: Bar<any, string>) => number
>(x: Foo<string>) => 1 : (x: Bar<any, string>) => number
>x : Bar<any, string>
>Foo : Bar<any, Y>
>1 : 1

View file

@ -0,0 +1,36 @@
//// [instantiatedTypeAliasDisplay.ts]
// Repros from #12066
interface X<A> {
a: A;
}
interface Y<B> {
b: B;
}
type Z<A, B> = X<A> | Y<B>;
declare function f1<A>(): Z<A, number>;
declare function f2<A, B, C, D, E>(a: A, b: B, c: C, d: D): Z<A, string[]>;
const x1 = f1<string>(); // Z<string, number>
const x2 = f2({}, {}, {}, {}); // Z<{}, string[]>
//// [instantiatedTypeAliasDisplay.js]
// Repros from #12066
var x1 = f1(); // Z<string, number>
var x2 = f2({}, {}, {}, {}); // Z<{}, string[]>
//// [instantiatedTypeAliasDisplay.d.ts]
interface X<A> {
a: A;
}
interface Y<B> {
b: B;
}
declare type Z<A, B> = X<A> | Y<B>;
declare function f1<A>(): Z<A, number>;
declare function f2<A, B, C, D, E>(a: A, b: B, c: C, d: D): Z<A, string[]>;
declare const x1: Z<string, number>;
declare const x2: Z<{}, string[]>;

View file

@ -0,0 +1,61 @@
=== tests/cases/compiler/instantiatedTypeAliasDisplay.ts ===
// Repros from #12066
interface X<A> {
>X : Symbol(X, Decl(instantiatedTypeAliasDisplay.ts, 0, 0))
>A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 3, 12))
a: A;
>a : Symbol(X.a, Decl(instantiatedTypeAliasDisplay.ts, 3, 16))
>A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 3, 12))
}
interface Y<B> {
>Y : Symbol(Y, Decl(instantiatedTypeAliasDisplay.ts, 5, 1))
>B : Symbol(B, Decl(instantiatedTypeAliasDisplay.ts, 6, 12))
b: B;
>b : Symbol(Y.b, Decl(instantiatedTypeAliasDisplay.ts, 6, 16))
>B : Symbol(B, Decl(instantiatedTypeAliasDisplay.ts, 6, 12))
}
type Z<A, B> = X<A> | Y<B>;
>Z : Symbol(Z, Decl(instantiatedTypeAliasDisplay.ts, 8, 1))
>A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 9, 7))
>B : Symbol(B, Decl(instantiatedTypeAliasDisplay.ts, 9, 9))
>X : Symbol(X, Decl(instantiatedTypeAliasDisplay.ts, 0, 0))
>A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 9, 7))
>Y : Symbol(Y, Decl(instantiatedTypeAliasDisplay.ts, 5, 1))
>B : Symbol(B, Decl(instantiatedTypeAliasDisplay.ts, 9, 9))
declare function f1<A>(): Z<A, number>;
>f1 : Symbol(f1, Decl(instantiatedTypeAliasDisplay.ts, 9, 27))
>A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 11, 20))
>Z : Symbol(Z, Decl(instantiatedTypeAliasDisplay.ts, 8, 1))
>A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 11, 20))
declare function f2<A, B, C, D, E>(a: A, b: B, c: C, d: D): Z<A, string[]>;
>f2 : Symbol(f2, Decl(instantiatedTypeAliasDisplay.ts, 11, 39))
>A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 12, 20))
>B : Symbol(B, Decl(instantiatedTypeAliasDisplay.ts, 12, 22))
>C : Symbol(C, Decl(instantiatedTypeAliasDisplay.ts, 12, 25))
>D : Symbol(D, Decl(instantiatedTypeAliasDisplay.ts, 12, 28))
>E : Symbol(E, Decl(instantiatedTypeAliasDisplay.ts, 12, 31))
>a : Symbol(a, Decl(instantiatedTypeAliasDisplay.ts, 12, 35))
>A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 12, 20))
>b : Symbol(b, Decl(instantiatedTypeAliasDisplay.ts, 12, 40))
>B : Symbol(B, Decl(instantiatedTypeAliasDisplay.ts, 12, 22))
>c : Symbol(c, Decl(instantiatedTypeAliasDisplay.ts, 12, 46))
>C : Symbol(C, Decl(instantiatedTypeAliasDisplay.ts, 12, 25))
>d : Symbol(d, Decl(instantiatedTypeAliasDisplay.ts, 12, 52))
>D : Symbol(D, Decl(instantiatedTypeAliasDisplay.ts, 12, 28))
>Z : Symbol(Z, Decl(instantiatedTypeAliasDisplay.ts, 8, 1))
>A : Symbol(A, Decl(instantiatedTypeAliasDisplay.ts, 12, 20))
const x1 = f1<string>(); // Z<string, number>
>x1 : Symbol(x1, Decl(instantiatedTypeAliasDisplay.ts, 14, 5))
>f1 : Symbol(f1, Decl(instantiatedTypeAliasDisplay.ts, 9, 27))
const x2 = f2({}, {}, {}, {}); // Z<{}, string[]>
>x2 : Symbol(x2, Decl(instantiatedTypeAliasDisplay.ts, 15, 5))
>f2 : Symbol(f2, Decl(instantiatedTypeAliasDisplay.ts, 11, 39))

View file

@ -0,0 +1,67 @@
=== tests/cases/compiler/instantiatedTypeAliasDisplay.ts ===
// Repros from #12066
interface X<A> {
>X : X<A>
>A : A
a: A;
>a : A
>A : A
}
interface Y<B> {
>Y : Y<B>
>B : B
b: B;
>b : B
>B : B
}
type Z<A, B> = X<A> | Y<B>;
>Z : Z<A, B>
>A : A
>B : B
>X : X<A>
>A : A
>Y : Y<B>
>B : B
declare function f1<A>(): Z<A, number>;
>f1 : <A>() => Z<A, number>
>A : A
>Z : Z<A, B>
>A : A
declare function f2<A, B, C, D, E>(a: A, b: B, c: C, d: D): Z<A, string[]>;
>f2 : <A, B, C, D, E>(a: A, b: B, c: C, d: D) => Z<A, string[]>
>A : A
>B : B
>C : C
>D : D
>E : E
>a : A
>A : A
>b : B
>B : B
>c : C
>C : C
>d : D
>D : D
>Z : Z<A, B>
>A : A
const x1 = f1<string>(); // Z<string, number>
>x1 : Z<string, number>
>f1<string>() : Z<string, number>
>f1 : <A>() => Z<A, number>
const x2 = f2({}, {}, {}, {}); // Z<{}, string[]>
>x2 : Z<{}, string[]>
>f2({}, {}, {}, {}) : Z<{}, string[]>
>f2 : <A, B, C, D, E>(a: A, b: B, c: C, d: D) => Z<A, string[]>
>{} : {}
>{} : {}
>{} : {}
>{} : {}

View file

@ -0,0 +1,17 @@
// @declaration: true
// Repros from #12066
interface X<A> {
a: A;
}
interface Y<B> {
b: B;
}
type Z<A, B> = X<A> | Y<B>;
declare function f1<A>(): Z<A, number>;
declare function f2<A, B, C, D, E>(a: A, b: B, c: C, d: D): Z<A, string[]>;
const x1 = f1<string>(); // Z<string, number>
const x2 = f2({}, {}, {}, {}); // Z<{}, string[]>