Merge pull request #550 from Microsoft/deferredTypeLiterals

Deferred resolution of object literal members to support recursive types.
This commit is contained in:
Anders Hejlsberg 2014-09-03 11:03:24 -07:00
commit dab3691af6
4 changed files with 38 additions and 29 deletions

View file

@ -1801,27 +1801,39 @@ module ts {
function resolveAnonymousTypeMembers(type: ObjectType) { function resolveAnonymousTypeMembers(type: ObjectType) {
var symbol = type.symbol; var symbol = type.symbol;
var members = emptySymbols; if (symbol.flags & SymbolFlags.TypeLiteral) {
var callSignatures = emptyArray; var members = symbol.members;
var constructSignatures = emptyArray; var callSignatures = getSignaturesOfSymbol(members["__call"]);
if (symbol.flags & SymbolFlags.HasExports) { var constructSignatures = getSignaturesOfSymbol(members["__new"]);
members = symbol.exports; var stringIndexType = getIndexTypeOfSymbol(symbol, IndexKind.String);
var numberIndexType = getIndexTypeOfSymbol(symbol, IndexKind.Number);
} }
if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method)) { else {
callSignatures = getSignaturesOfSymbol(symbol); // Combinations of function, class, enum and module
} var members = emptySymbols;
if (symbol.flags & SymbolFlags.Class) { var callSignatures: Signature[] = emptyArray;
var classType = getDeclaredTypeOfClass(symbol); var constructSignatures: Signature[] = emptyArray;
constructSignatures = getSignaturesOfSymbol(symbol.members["__constructor"]); if (symbol.flags & SymbolFlags.HasExports) {
if (!constructSignatures.length) constructSignatures = getDefaultConstructSignatures(classType); members = symbol.exports;
if (classType.baseTypes.length) {
var members = createSymbolTable(getNamedMembers(members));
addInheritedMembers(members, getPropertiesOfType(getTypeOfSymbol(classType.baseTypes[0].symbol)));
} }
if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method)) {
callSignatures = getSignaturesOfSymbol(symbol);
}
if (symbol.flags & SymbolFlags.Class) {
var classType = getDeclaredTypeOfClass(symbol);
constructSignatures = getSignaturesOfSymbol(symbol.members["__constructor"]);
if (!constructSignatures.length) {
constructSignatures = getDefaultConstructSignatures(classType);
}
if (classType.baseTypes.length) {
members = createSymbolTable(getNamedMembers(members));
addInheritedMembers(members, getPropertiesOfType(getTypeOfSymbol(classType.baseTypes[0].symbol)));
}
}
var stringIndexType: Type = undefined;
var numberIndexType: Type = (symbol.flags & SymbolFlags.Enum) ? stringType : undefined;
} }
var numberIndexType = (symbol.flags & SymbolFlags.Enum) ? stringType : undefined; setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexType, numberIndexType);
setObjectTypeMembers(type, members, callSignatures, constructSignatures, /* stringIndexType */ undefined, numberIndexType);
} }
function resolveObjectTypeMembers(type: ObjectType): ResolvedObjectType { function resolveObjectTypeMembers(type: ObjectType): ResolvedObjectType {
@ -2276,13 +2288,8 @@ module ts {
function getTypeFromTypeLiteralNode(node: TypeLiteralNode): Type { function getTypeFromTypeLiteralNode(node: TypeLiteralNode): Type {
var links = getNodeLinks(node); var links = getNodeLinks(node);
if (!links.resolvedType) { if (!links.resolvedType) {
var symbol = node.symbol; // Deferred resolution of members is handled by resolveObjectTypeMembers
var members = symbol.members; links.resolvedType = createObjectType(TypeFlags.Anonymous, node.symbol);
var callSignatures = getSignaturesOfSymbol(members["__call"]);
var constructSignatures = getSignaturesOfSymbol(members["__new"]);
var stringIndexType = getIndexTypeOfSymbol(symbol, IndexKind.String);
var numberIndexType = getIndexTypeOfSymbol(symbol, IndexKind.Number);
links.resolvedType = createAnonymousType(symbol, members, callSignatures, constructSignatures, stringIndexType, numberIndexType);
} }
return links.resolvedType; return links.resolvedType;
} }

View file

@ -68,7 +68,7 @@ declare function f(n: typeof f): string;
declare function f(n: typeof g): string; declare function f(n: typeof g): string;
declare function g(n: typeof g): number; declare function g(n: typeof g): number;
declare function g(n: typeof f): number; declare function g(n: typeof f): number;
declare var b: any; declare var b: () => any;
declare function b1(): typeof b1; declare function b1(): typeof b1;
declare function foo(): typeof foo; declare function foo(): typeof foo;
declare var foo1: typeof foo; declare var foo1: typeof foo;

View file

@ -29,8 +29,8 @@ function g() { return undefined; }
>undefined : undefined >undefined : undefined
var b: () => typeof b; var b: () => typeof b;
>b : any >b : () => any
>b : any >b : () => any
function b1() { function b1() {
>b1 : () => typeof b1 >b1 : () => typeof b1

View file

@ -1,4 +1,4 @@
==== tests/cases/compiler/recursiveFunctionTypes.ts (12 errors) ==== ==== tests/cases/compiler/recursiveFunctionTypes.ts (13 errors) ====
function fn(): typeof fn { return 1; } function fn(): typeof fn { return 1; }
~ ~
!!! Type 'number' is not assignable to type '() => typeof fn'. !!! Type 'number' is not assignable to type '() => typeof fn'.
@ -39,6 +39,8 @@
var f4: () => typeof f4; var f4: () => typeof f4;
f4 = 3; // error f4 = 3; // error
~~
!!! Type 'number' is not assignable to type '() => any'.
function f5() { return f5; } function f5() { return f5; }