diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 4eb8c48192..37ac1dd9ef 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -306,10 +306,23 @@ module ts { } function bindFunctionOrConstructorType(node: SignatureDeclaration) { + // For a given function type "<...>(...) => T" we want to generate a type identical + // to: { <...>(...): T } + // + // We do that by making an anonymous type literal type, that points to an anonymous + // type literal symbol, and then setting the function symbol as its sole of the type + // literal symbol. To the rest of the system, this type will be indistinguishable + // from an actual type literal type you would have gotten had you used the long form. + var symbolKind = node.kind === SyntaxKind.FunctionType ? SymbolFlags.CallSignature : SymbolFlags.ConstructSignature; var symbol = createSymbol(symbolKind, getDeclarationName(node)); addDeclarationToSymbol(symbol, node, symbolKind); bindChildren(node, symbolKind, /*isBlockScopeContainer:*/ false); + + var typeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, "__type"); + addDeclarationToSymbol(typeLiteralSymbol, node, SymbolFlags.TypeLiteral); + typeLiteralSymbol.members = {}; + typeLiteralSymbol.members[node.kind === SyntaxKind.FunctionType ? "__call" : "__new"] = symbol } function bindAnonymousDeclaration(node: Node, symbolKind: SymbolFlags, name: string, isBlockScopeContainer: boolean) { diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8177db9ee1..76ce1eda18 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2962,32 +2962,8 @@ module ts { } return links.resolvedType; } - - function getTypefromFunctionOrConstructorTypeNode(node: SignatureDeclaration): Type { - var links = getNodeLinks(node); - if (!links.resolvedType) { - // For a given function type "<...>(...) => T" we want to generate a type identical - // to: { <...>(...): T } - // - // We do that by making an anonymous type literal type, that points to an anonymous - // type literal symbol, and then setting the function symbol as its sole of the type - // literal symbol. To the rest of the checker, this type will be indistinguishable - // from an actual type literal type you would have gotten had you used the long form. - var symbol = new Symbol(SymbolFlags.TypeLiteral | SymbolFlags.Transient, "__type"); - symbol.members = {}; - symbol.members[node.kind === SyntaxKind.FunctionType ? "__call" : "__new"] = node.symbol; - - Debug.assert(node.symbol.declarations.length === 1); - symbol.declarations = [node.symbol.declarations[0]]; - - node.symbol.parent = symbol; - - links.resolvedType = createObjectType(TypeFlags.Anonymous, symbol); - } - return links.resolvedType; - } - - function getTypeFromTypeLiteralNode(node: TypeLiteralNode): Type { + + function getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node: Node): Type { var links = getNodeLinks(node); if (!links.resolvedType) { // Deferred resolution of members is handled by resolveObjectTypeMembers @@ -3039,9 +3015,8 @@ module ts { return getTypeFromTypeNode((node).type); case SyntaxKind.FunctionType: case SyntaxKind.ConstructorType: - return getTypefromFunctionOrConstructorTypeNode(node); case SyntaxKind.TypeLiteral: - return getTypeFromTypeLiteralNode(node); + return getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node); // This function assumes that an identifier or qualified name is a type expression // Callers should first ensure this by calling isTypeNode case SyntaxKind.Identifier: @@ -6834,7 +6809,7 @@ module ts { function checkTypeLiteral(node: TypeLiteralNode) { forEach(node.members, checkSourceElement); if (fullTypeCheck) { - var type = getTypeFromTypeLiteralNode(node); + var type = getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node); checkIndexConstraints(type); checkTypeForDuplicateIndexSignatures(node); }