From fbe4246d39d2f001160948855b61a492094d44fd Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Wed, 15 Jul 2015 16:36:54 -0700 Subject: [PATCH 1/6] Remove resolveLocation --- src/compiler/checker.ts | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 007edacadc9..d0c5667a340 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5841,32 +5841,15 @@ namespace ts { } } - function resolveLocation(node: Node) { - // Resolve location from top down towards node if it is a context sensitive expression - // That helps in making sure not assigning types as any when resolved out of order - let containerNodes: Node[] = []; - for (let parent = node.parent; parent; parent = parent.parent) { - if ((isExpression(parent) || isObjectLiteralMethod(node)) && - isContextSensitive(parent)) { - containerNodes.unshift(parent); - } - } - - ts.forEach(containerNodes, node => { getTypeOfNode(node); }); - } - function getSymbolAtLocation(node: Node): Symbol { - resolveLocation(node); return getSymbolInfo(node); } function getTypeAtLocation(node: Node): Type { - resolveLocation(node); return getTypeOfNode(node); } function getTypeOfSymbolAtLocation(symbol: Symbol, node: Node): Type { - resolveLocation(node); // Get the narrowed type of symbol at given location instead of just getting // the type of the symbol. // eg. From 48588b622e50d2e90ea8aae1f856e9483f2c476b Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Thu, 16 Jul 2015 18:17:28 -0700 Subject: [PATCH 2/6] Only consider a type resolution sequence a cycle if none of the items in the sequence have types --- src/compiler/checker.ts | 49 ++++++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d0c5667a340..9211437b42f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -161,6 +161,7 @@ namespace ts { let resolutionTargets: Object[] = []; let resolutionResults: boolean[] = []; + let resolutionKinds: TypeSystemObjectKind[] = []; let mergedSymbols: Symbol[] = []; let symbolLinks: SymbolLinks[] = []; @@ -201,6 +202,13 @@ namespace ts { let assignableRelation: Map = {}; let identityRelation: Map = {}; + enum TypeSystemObjectKind { + Symbol, + Type, + SymbolLinks, + Signature + } + initializeTypeChecker(); return checker; @@ -2184,13 +2192,14 @@ namespace ts { // a unique identity for a particular type resolution result: Symbol instances are used to track resolution of // SymbolLinks.type, SymbolLinks instances are used to track resolution of SymbolLinks.declaredType, and // Signature instances are used to track resolution of Signature.resolvedReturnType. - function pushTypeResolution(target: Object): boolean { - let i = 0; + function pushTypeResolution(target: Object, flags: TypeSystemObjectKind): boolean { let count = resolutionTargets.length; - while (i < count && resolutionTargets[i] !== target) { - i++; + let i = count - 1; + let foundGoodType = false; + while (i >= 0 && !(foundGoodType = !!hasType(resolutionTargets[i], resolutionKinds[i])) && resolutionTargets[i] !== target) { + i--; } - if (i < count) { + if (i >= 0 && !foundGoodType) { do { resolutionResults[i++] = false; } @@ -2199,13 +2208,33 @@ namespace ts { } resolutionTargets.push(target); resolutionResults.push(true); + resolutionKinds.push(flags); return true; } + function hasType(target: Object, flags: TypeSystemObjectKind): Type { + if (flags === TypeSystemObjectKind.Symbol) { + return getSymbolLinks(target).type; + } + else if (flags === TypeSystemObjectKind.Type) { + Debug.assert(!!((target).flags & TypeFlags.Class)); + return (target).resolvedBaseConstructorType; + } + else if (flags === TypeSystemObjectKind.SymbolLinks) { + return (target).declaredType; + } + else if (flags === TypeSystemObjectKind.Signature) { + return (target).resolvedReturnType; + } + + Debug.fail("Unhandled TypeSystemObjectKind"); + } + // Pop an entry from the type resolution stack and return its associated result value. The result value will // be true if no circularities were detected, or false if a circularity was found. function popTypeResolution(): boolean { resolutionTargets.pop(); + resolutionKinds.pop(); return resolutionResults.pop(); } @@ -2468,7 +2497,7 @@ namespace ts { return links.type = checkExpression((declaration).expression); } // Handle variable, parameter or property - if (!pushTypeResolution(symbol)) { + if (!pushTypeResolution(symbol, TypeSystemObjectKind.Symbol)) { return unknownType; } let type = getWidenedTypeForVariableLikeDeclaration(declaration, /*reportErrors*/ true); @@ -2509,7 +2538,7 @@ namespace ts { function getTypeOfAccessors(symbol: Symbol): Type { let links = getSymbolLinks(symbol); if (!links.type) { - if (!pushTypeResolution(symbol)) { + if (!pushTypeResolution(symbol, TypeSystemObjectKind.Symbol)) { return unknownType; } let getter = getDeclarationOfKind(symbol, SyntaxKind.GetAccessor); @@ -2725,7 +2754,7 @@ namespace ts { if (!baseTypeNode) { return type.resolvedBaseConstructorType = undefinedType; } - if (!pushTypeResolution(type)) { + if (!pushTypeResolution(type, TypeSystemObjectKind.Type)) { return unknownType; } let baseConstructorType = checkExpression(baseTypeNode.expression); @@ -2852,7 +2881,7 @@ namespace ts { if (!links.declaredType) { // Note that we use the links object as the target here because the symbol object is used as the unique // identity for resolution of the 'type' property in SymbolLinks. - if (!pushTypeResolution(links)) { + if (!pushTypeResolution(links, TypeSystemObjectKind.SymbolLinks)) { return unknownType; } let declaration = getDeclarationOfKind(symbol, SyntaxKind.TypeAliasDeclaration); @@ -3539,7 +3568,7 @@ namespace ts { function getReturnTypeOfSignature(signature: Signature): Type { if (!signature.resolvedReturnType) { - if (!pushTypeResolution(signature)) { + if (!pushTypeResolution(signature, TypeSystemObjectKind.Signature)) { return unknownType; } let type: Type; From c0b3835b19685ed9b71ad1686b5e6308f3c03e87 Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Fri, 17 Jul 2015 16:32:40 -0700 Subject: [PATCH 3/6] Instantiate signatures if there is an overload resolution error but type arguments present --- src/compiler/checker.ts | 3 +++ tests/cases/fourslash/genericCombinators2.ts | 6 +++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9211437b42f..bf4f6e07b73 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8522,6 +8522,9 @@ namespace ts { if (!produceDiagnostics) { for (let candidate of candidates) { if (hasCorrectArity(node, args, candidate)) { + if (candidate.typeParameters && typeArguments) { + candidate = getSignatureInstantiation(candidate, map(typeArguments, getTypeFromTypeNode)); + } return candidate; } } diff --git a/tests/cases/fourslash/genericCombinators2.ts b/tests/cases/fourslash/genericCombinators2.ts index 4d38ffd0796..bcd96dcd1c6 100644 --- a/tests/cases/fourslash/genericCombinators2.ts +++ b/tests/cases/fourslash/genericCombinators2.ts @@ -110,7 +110,7 @@ goTo.marker('15'); verify.quickInfoIs('var r4a: Collection'); goTo.marker('17'); -verify.quickInfoIs('var r5a: Collection'); // This is actually due to an error because toFixed does not return a Date +verify.quickInfoIs('var r5a: Collection'); goTo.marker('18'); verify.quickInfoIs('var r5b: Collection'); @@ -122,10 +122,10 @@ goTo.marker('20'); verify.quickInfoIs('var r6b: Collection, Date>'); goTo.marker('21'); -verify.quickInfoIs('var r7a: Collection'); // This call is an error because y.foo() does not return a string +verify.quickInfoIs('var r7a: Collection'); goTo.marker('22'); -verify.quickInfoIs('var r7b: Collection'); // This call is an error because y.foo() does not return a string +verify.quickInfoIs('var r7b: Collection'); goTo.marker('23'); verify.quickInfoIs('var r8a: Collection'); From 3b78377cf0de87c3d17b6fd27b0627001a82b901 Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Fri, 17 Jul 2015 17:01:37 -0700 Subject: [PATCH 4/6] Clean up pushTypeResolution --- src/compiler/checker.ts | 89 +++++++++++++++++++++++------------------ src/compiler/types.ts | 2 + 2 files changed, 53 insertions(+), 38 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index bf4f6e07b73..927e20b5d27 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -159,9 +159,9 @@ namespace ts { let emitAwaiter = false; let emitGenerator = false; - let resolutionTargets: Object[] = []; + let resolutionTargets: TypeSystemEntity[] = []; let resolutionResults: boolean[] = []; - let resolutionKinds: TypeSystemObjectKind[] = []; + let resolutionPropertyNames: TypeSystemPropertyName[] = []; let mergedSymbols: Symbol[] = []; let symbolLinks: SymbolLinks[] = []; @@ -202,11 +202,11 @@ namespace ts { let assignableRelation: Map = {}; let identityRelation: Map = {}; - enum TypeSystemObjectKind { - Symbol, + enum TypeSystemPropertyName { Type, - SymbolLinks, - Signature + ResolvedBaseConstructorType, + DeclaredType, + ResolvedReturnType } initializeTypeChecker(); @@ -2185,45 +2185,58 @@ namespace ts { } } - // Push an entry on the type resolution stack. If an entry with the given target is not already on the stack, - // a new entry with that target and an associated result value of true is pushed on the stack, and the value - // true is returned. Otherwise, a circularity has occurred and the result values of the existing entry and - // all entries pushed after it are changed to false, and the value false is returned. The target object provides - // a unique identity for a particular type resolution result: Symbol instances are used to track resolution of - // SymbolLinks.type, SymbolLinks instances are used to track resolution of SymbolLinks.declaredType, and - // Signature instances are used to track resolution of Signature.resolvedReturnType. - function pushTypeResolution(target: Object, flags: TypeSystemObjectKind): boolean { - let count = resolutionTargets.length; - let i = count - 1; - let foundGoodType = false; - while (i >= 0 && !(foundGoodType = !!hasType(resolutionTargets[i], resolutionKinds[i])) && resolutionTargets[i] !== target) { - i--; - } - if (i >= 0 && !foundGoodType) { - do { - resolutionResults[i++] = false; + /** + * Push an entry on the type resolution stack. If an entry with the given target and the given property name + * is already on the stack, and no entries in between already have a type, then a circularity has occurred. + * In this case, the result values of the existing entry and all entries pushed after it are changed to false, + * and the value false is returned. Otherwise, the new entry is just pushed onto the stack, and true is returned. + * In order to see if the same query has already been done before, the target object and the propertyName both + * must match the one passed in. + * + * @param target The symbol, type, or signature whose type is being queried + * @param propertyName The property name that should be used to query the target for its type + */ + function pushTypeResolution(target: TypeSystemEntity, propertyName: TypeSystemPropertyName): boolean { + let resolutionCycleStartIndex = findResolutionCycleStartIndex(target, propertyName); + if (resolutionCycleStartIndex >= 0) { + // A cycle was found + let { length } = resolutionTargets; + for (let i = resolutionCycleStartIndex; i < length; i++) { + resolutionResults[i] = false; } - while (i < count); return false; } resolutionTargets.push(target); resolutionResults.push(true); - resolutionKinds.push(flags); + resolutionPropertyNames.push(propertyName); return true; } - function hasType(target: Object, flags: TypeSystemObjectKind): Type { - if (flags === TypeSystemObjectKind.Symbol) { + function findResolutionCycleStartIndex(target: TypeSystemEntity, propertyName: TypeSystemPropertyName): number { + for (let i = resolutionTargets.length - 1; i >= 0; i--) { + if (hasType(resolutionTargets[i], resolutionPropertyNames[i])) { + return -1; + } + if (resolutionTargets[i] === target && resolutionPropertyNames[i] === propertyName) { + return i; + } + } + + return -1; + } + + function hasType(target: TypeSystemEntity, propertyName: TypeSystemPropertyName): Type { + if (propertyName === TypeSystemPropertyName.Type) { return getSymbolLinks(target).type; } - else if (flags === TypeSystemObjectKind.Type) { + else if (propertyName === TypeSystemPropertyName.DeclaredType) { + return getSymbolLinks(target).declaredType; + } + else if (propertyName === TypeSystemPropertyName.ResolvedBaseConstructorType) { Debug.assert(!!((target).flags & TypeFlags.Class)); return (target).resolvedBaseConstructorType; } - else if (flags === TypeSystemObjectKind.SymbolLinks) { - return (target).declaredType; - } - else if (flags === TypeSystemObjectKind.Signature) { + else if (propertyName === TypeSystemPropertyName.ResolvedReturnType) { return (target).resolvedReturnType; } @@ -2234,7 +2247,7 @@ namespace ts { // be true if no circularities were detected, or false if a circularity was found. function popTypeResolution(): boolean { resolutionTargets.pop(); - resolutionKinds.pop(); + resolutionPropertyNames.pop(); return resolutionResults.pop(); } @@ -2497,7 +2510,7 @@ namespace ts { return links.type = checkExpression((declaration).expression); } // Handle variable, parameter or property - if (!pushTypeResolution(symbol, TypeSystemObjectKind.Symbol)) { + if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) { return unknownType; } let type = getWidenedTypeForVariableLikeDeclaration(declaration, /*reportErrors*/ true); @@ -2538,7 +2551,7 @@ namespace ts { function getTypeOfAccessors(symbol: Symbol): Type { let links = getSymbolLinks(symbol); if (!links.type) { - if (!pushTypeResolution(symbol, TypeSystemObjectKind.Symbol)) { + if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) { return unknownType; } let getter = getDeclarationOfKind(symbol, SyntaxKind.GetAccessor); @@ -2754,7 +2767,7 @@ namespace ts { if (!baseTypeNode) { return type.resolvedBaseConstructorType = undefinedType; } - if (!pushTypeResolution(type, TypeSystemObjectKind.Type)) { + if (!pushTypeResolution(type, TypeSystemPropertyName.ResolvedBaseConstructorType)) { return unknownType; } let baseConstructorType = checkExpression(baseTypeNode.expression); @@ -2881,7 +2894,7 @@ namespace ts { if (!links.declaredType) { // Note that we use the links object as the target here because the symbol object is used as the unique // identity for resolution of the 'type' property in SymbolLinks. - if (!pushTypeResolution(links, TypeSystemObjectKind.SymbolLinks)) { + if (!pushTypeResolution(symbol, TypeSystemPropertyName.DeclaredType)) { return unknownType; } let declaration = getDeclarationOfKind(symbol, SyntaxKind.TypeAliasDeclaration); @@ -3568,7 +3581,7 @@ namespace ts { function getReturnTypeOfSignature(signature: Signature): Type { if (!signature.resolvedReturnType) { - if (!pushTypeResolution(signature, TypeSystemObjectKind.Signature)) { + if (!pushTypeResolution(signature, TypeSystemPropertyName.ResolvedReturnType)) { return unknownType; } let type: Type; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index f1b476d11b4..edaf940e2fc 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1904,6 +1904,8 @@ namespace ts { isolatedSignatureType?: ObjectType; // A manufactured type that just contains the signature for purposes of signature comparison } + export type TypeSystemEntity = Symbol | Type | Signature; + export const enum IndexKind { String, Number, From e2303b1ae865f150c3102fe5b370d51b4aa7d88d Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Fri, 17 Jul 2015 17:22:17 -0700 Subject: [PATCH 5/6] Clean up the language service aliases to check functions --- src/compiler/checker.ts | 59 +++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 35 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 927e20b5d27..7281d0d6059 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -59,7 +59,20 @@ namespace ts { isArgumentsSymbol: symbol => symbol === argumentsSymbol, getDiagnostics, getGlobalDiagnostics, - getTypeOfSymbolAtLocation, + + // Get the narrowed type of symbol at given location instead of just getting + // the type of the symbol. + // eg. + // function foo(a: string | number) { + // if (typeof a === "string") { + // a/**/ + // } + // } + // getTypeOfSymbol for a would return type of parameter symbol string | number + // Unless we provide location /**/, checker wouldn't know how to narrow the type + // By using getNarrowedTypeOfSymbol would return string since it would be able to narrow + // it by typeguard in the if true condition + getTypeOfSymbolAtLocation: getNarrowedTypeOfSymbol, getDeclaredTypeOfSymbol, getPropertiesOfType, getPropertyOfType, @@ -69,7 +82,7 @@ namespace ts { getSymbolsInScope, getSymbolAtLocation, getShorthandAssignmentValueSymbol, - getTypeAtLocation, + getTypeAtLocation: getTypeOfNode, typeToString, getSymbolDisplayBuilder, symbolToString, @@ -4226,7 +4239,7 @@ namespace ts { // Callers should first ensure this by calling isTypeNode case SyntaxKind.Identifier: case SyntaxKind.QualifiedName: - let symbol = getSymbolInfo(node); + let symbol = getSymbolAtLocation(node); return symbol && getDeclaredTypeOfSymbol(symbol); default: return unknownType; @@ -5883,30 +5896,6 @@ namespace ts { } } - function getSymbolAtLocation(node: Node): Symbol { - return getSymbolInfo(node); - } - - function getTypeAtLocation(node: Node): Type { - return getTypeOfNode(node); - } - - function getTypeOfSymbolAtLocation(symbol: Symbol, node: Node): Type { - // Get the narrowed type of symbol at given location instead of just getting - // the type of the symbol. - // eg. - // function foo(a: string | number) { - // if (typeof a === "string") { - // a/**/ - // } - // } - // getTypeOfSymbol for a would return type of parameter symbol string | number - // Unless we provide location /**/, checker wouldn't know how to narrow the type - // By using getNarrowedTypeOfSymbol would return string since it would be able to narrow - // it by typeguard in the if true condition - return getNarrowedTypeOfSymbol(symbol, node); - } - // Get the narrowed type of a given symbol at a given location function getNarrowedTypeOfSymbol(symbol: Symbol, node: Node) { let type = getTypeOfSymbol(symbol); @@ -10136,7 +10125,7 @@ namespace ts { } else { checkTypeAssignableTo(typePredicate.type, - getTypeAtLocation(node.parameters[typePredicate.parameterIndex]), + getTypeOfNode(node.parameters[typePredicate.parameterIndex]), typePredicateNode.type); } } @@ -13758,7 +13747,7 @@ namespace ts { return undefined; } - function getSymbolInfo(node: Node) { + function getSymbolAtLocation(node: Node) { if (isInsideWithStatementBody(node)) { // We cannot answer semantic questions within a with block, do not proceed any further return undefined; @@ -13778,7 +13767,7 @@ namespace ts { else if (node.parent.kind === SyntaxKind.BindingElement && node.parent.parent.kind === SyntaxKind.ObjectBindingPattern && node === (node.parent).propertyName) { - let typeOfPattern = getTypeAtLocation(node.parent.parent); + let typeOfPattern = getTypeOfNode(node.parent.parent); let propertyDeclaration = typeOfPattern && getPropertyOfType(typeOfPattern, (node).text); if (propertyDeclaration) { @@ -13861,24 +13850,24 @@ namespace ts { } if (isTypeDeclaration(node)) { - // In this case, we call getSymbolOfNode instead of getSymbolInfo because it is a declaration + // In this case, we call getSymbolOfNode instead of getSymbolAtLocation because it is a declaration let symbol = getSymbolOfNode(node); return getDeclaredTypeOfSymbol(symbol); } if (isTypeDeclarationName(node)) { - let symbol = getSymbolInfo(node); + let symbol = getSymbolAtLocation(node); return symbol && getDeclaredTypeOfSymbol(symbol); } if (isDeclaration(node)) { - // In this case, we call getSymbolOfNode instead of getSymbolInfo because it is a declaration + // In this case, we call getSymbolOfNode instead of getSymbolAtLocation because it is a declaration let symbol = getSymbolOfNode(node); return getTypeOfSymbol(symbol); } if (isDeclarationName(node)) { - let symbol = getSymbolInfo(node); + let symbol = getSymbolAtLocation(node); return symbol && getTypeOfSymbol(symbol); } @@ -13887,7 +13876,7 @@ namespace ts { } if (isInRightSideOfImportOrExportAssignment(node)) { - let symbol = getSymbolInfo(node); + let symbol = getSymbolAtLocation(node); let declaredType = symbol && getDeclaredTypeOfSymbol(symbol); return declaredType !== unknownType ? declaredType : getTypeOfSymbol(symbol); } From 05bc4fecb1778c79262505be54a0b095a66b33b2 Mon Sep 17 00:00:00 2001 From: Jason Freeman Date: Mon, 20 Jul 2015 13:40:03 -0700 Subject: [PATCH 6/6] Address PR feedback --- src/compiler/checker.ts | 26 +++++++++----------------- src/compiler/types.ts | 2 -- 2 files changed, 9 insertions(+), 19 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7281d0d6059..c8b558e91d4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -60,18 +60,8 @@ namespace ts { getDiagnostics, getGlobalDiagnostics, - // Get the narrowed type of symbol at given location instead of just getting - // the type of the symbol. - // eg. - // function foo(a: string | number) { - // if (typeof a === "string") { - // a/**/ - // } - // } - // getTypeOfSymbol for a would return type of parameter symbol string | number - // Unless we provide location /**/, checker wouldn't know how to narrow the type - // By using getNarrowedTypeOfSymbol would return string since it would be able to narrow - // it by typeguard in the if true condition + // The language service will always care about the narrowed type of a symbol, because that is + // the type the language says the symbol should have. getTypeOfSymbolAtLocation: getNarrowedTypeOfSymbol, getDeclaredTypeOfSymbol, getPropertiesOfType, @@ -215,7 +205,9 @@ namespace ts { let assignableRelation: Map = {}; let identityRelation: Map = {}; - enum TypeSystemPropertyName { + type TypeSystemEntity = Symbol | Type | Signature; + + const enum TypeSystemPropertyName { Type, ResolvedBaseConstructorType, DeclaredType, @@ -2242,18 +2234,18 @@ namespace ts { if (propertyName === TypeSystemPropertyName.Type) { return getSymbolLinks(target).type; } - else if (propertyName === TypeSystemPropertyName.DeclaredType) { + if (propertyName === TypeSystemPropertyName.DeclaredType) { return getSymbolLinks(target).declaredType; } - else if (propertyName === TypeSystemPropertyName.ResolvedBaseConstructorType) { + if (propertyName === TypeSystemPropertyName.ResolvedBaseConstructorType) { Debug.assert(!!((target).flags & TypeFlags.Class)); return (target).resolvedBaseConstructorType; } - else if (propertyName === TypeSystemPropertyName.ResolvedReturnType) { + if (propertyName === TypeSystemPropertyName.ResolvedReturnType) { return (target).resolvedReturnType; } - Debug.fail("Unhandled TypeSystemObjectKind"); + Debug.fail("Unhandled TypeSystemPropertyName " + propertyName); } // Pop an entry from the type resolution stack and return its associated result value. The result value will diff --git a/src/compiler/types.ts b/src/compiler/types.ts index edaf940e2fc..f1b476d11b4 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1904,8 +1904,6 @@ namespace ts { isolatedSignatureType?: ObjectType; // A manufactured type that just contains the signature for purposes of signature comparison } - export type TypeSystemEntity = Symbol | Type | Signature; - export const enum IndexKind { String, Number,