@@ -5045,42 +5045,29 @@ namespace ts {
50455045 return t => t === source1 ? target1 : t === source2 ? target2 : t;
50465046 }
50475047
5048- function createTypeMapper(sources: Type[], targets: Type[]): TypeMapper {
5049- switch (sources.length) {
5050- case 1: return createUnaryTypeMapper(sources[0], targets[0]);
5051- case 2: return createBinaryTypeMapper(sources[0], targets[0], sources[1], targets[1]);
5052- }
5048+ function createArrayTypeMapper(sources: Type[], targets: Type[]): TypeMapper {
50535049 return t => {
50545050 for (let i = 0; i < sources.length; i++) {
50555051 if (t === sources[i]) {
5056- return targets[i];
5052+ return targets ? targets [i] : anyType ;
50575053 }
50585054 }
50595055 return t;
50605056 };
50615057 }
50625058
5063- function createUnaryTypeEraser(source: Type): TypeMapper {
5064- return t => t === source ? anyType : t;
5065- }
5066-
5067- function createBinaryTypeEraser(source1: Type, source2: Type): TypeMapper {
5068- return t => t === source1 || t === source2 ? anyType : t;
5059+ function createTypeMapper(sources: Type[], targets: Type[]): TypeMapper {
5060+ const count = sources.length;
5061+ const mapper: TypeMapper =
5062+ count == 1 ? createUnaryTypeMapper(sources[0], targets ? targets[0] : anyType) :
5063+ count == 2 ? createBinaryTypeMapper(sources[0], targets ? targets[0] : anyType, sources[1], targets ? targets[1] : anyType) :
5064+ createArrayTypeMapper(sources, targets);
5065+ mapper.mappedTypes = sources;
5066+ return mapper;
50695067 }
50705068
50715069 function createTypeEraser(sources: Type[]): TypeMapper {
5072- switch (sources.length) {
5073- case 1: return createUnaryTypeEraser(sources[0]);
5074- case 2: return createBinaryTypeEraser(sources[0], sources[1]);
5075- }
5076- return t => {
5077- for (const source of sources) {
5078- if (t === source) {
5079- return anyType;
5080- }
5081- }
5082- return t;
5083- };
5070+ return createTypeMapper(sources, undefined);
50845071 }
50855072
50865073 function getInferenceMapper(context: InferenceContext): TypeMapper {
@@ -5095,6 +5082,7 @@ namespace ts {
50955082 }
50965083 return t;
50975084 };
5085+ mapper.mappedTypes = context.typeParameters;
50985086 mapper.context = context;
50995087 context.mapper = mapper;
51005088 }
@@ -5106,7 +5094,9 @@ namespace ts {
51065094 }
51075095
51085096 function combineTypeMappers(mapper1: TypeMapper, mapper2: TypeMapper): TypeMapper {
5109- return t => instantiateType(mapper1(t), mapper2);
5097+ const mapper: TypeMapper = t => instantiateType(mapper1(t), mapper2);
5098+ mapper.mappedTypes = mapper1.mappedTypes;
5099+ return mapper;
51105100 }
51115101
51125102 function cloneTypeParameter(typeParameter: TypeParameter): TypeParameter {
@@ -5201,13 +5191,70 @@ namespace ts {
52015191 return result;
52025192 }
52035193
5194+ function isSymbolInScopeOfMappedTypeParameter(symbol: Symbol, mapper: TypeMapper) {
5195+ const mappedTypes = mapper.mappedTypes;
5196+ // Starting with the parent of the symbol's declaration, check if the mapper maps any of
5197+ // the type parameters introduced by enclosing declarations. We just pick the first
5198+ // declaration since multiple declarations will all have the same parent anyway.
5199+ let node = symbol.declarations[0].parent;
5200+ while (node) {
5201+ switch (node.kind) {
5202+ case SyntaxKind.FunctionType:
5203+ case SyntaxKind.ConstructorType:
5204+ case SyntaxKind.FunctionDeclaration:
5205+ case SyntaxKind.MethodDeclaration:
5206+ case SyntaxKind.MethodSignature:
5207+ case SyntaxKind.Constructor:
5208+ case SyntaxKind.CallSignature:
5209+ case SyntaxKind.ConstructSignature:
5210+ case SyntaxKind.IndexSignature:
5211+ case SyntaxKind.GetAccessor:
5212+ case SyntaxKind.SetAccessor:
5213+ case SyntaxKind.FunctionExpression:
5214+ case SyntaxKind.ArrowFunction:
5215+ case SyntaxKind.ClassDeclaration:
5216+ case SyntaxKind.ClassExpression:
5217+ case SyntaxKind.InterfaceDeclaration:
5218+ case SyntaxKind.TypeAliasDeclaration:
5219+ const declaration = <DeclarationWithTypeParameters>node;
5220+ if (declaration.typeParameters) {
5221+ for (const d of declaration.typeParameters) {
5222+ if (contains(mappedTypes, getDeclaredTypeOfTypeParameter(d.symbol))) {
5223+ return true;
5224+ }
5225+ }
5226+ }
5227+ if (isClassLike(node) || node.kind === SyntaxKind.InterfaceDeclaration) {
5228+ const thisType = getDeclaredTypeOfClassOrInterface(getSymbolOfNode(node)).thisType;
5229+ if (thisType && contains(mappedTypes, thisType)) {
5230+ return true;
5231+ }
5232+ }
5233+ break;
5234+ case SyntaxKind.ModuleDeclaration:
5235+ case SyntaxKind.SourceFile:
5236+ return false;
5237+ }
5238+ node = node.parent;
5239+ }
5240+ return false;
5241+ }
5242+
52045243 function instantiateType(type: Type, mapper: TypeMapper): Type {
52055244 if (type && mapper !== identityMapper) {
52065245 if (type.flags & TypeFlags.TypeParameter) {
52075246 return mapper(<TypeParameter>type);
52085247 }
52095248 if (type.flags & TypeFlags.Anonymous) {
5210- return type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral) ?
5249+ // If the anonymous type originates in a declaration of a function, method, class, or
5250+ // interface, in an object type literal, or in an object literal expression, we may need
5251+ // to instantiate the type because it might reference a type parameter. We skip instantiation
5252+ // if none of the type parameters that are in scope in the type's declaration are mapped by
5253+ // the given mapper, however we can only do that analysis if the type isn't itself an
5254+ // instantiation.
5255+ return type.symbol &&
5256+ type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral) &&
5257+ (type.flags & TypeFlags.Instantiated || isSymbolInScopeOfMappedTypeParameter(type.symbol, mapper)) ?
52115258 instantiateAnonymousType(<AnonymousType>type, mapper) : type;
52125259 }
52135260 if (type.flags & TypeFlags.Reference) {
0 commit comments