Skip to content

Commit f4d3c1c

Browse files
committed
Deferred resolution of object literal members to support recursive types.
1 parent 211008d commit f4d3c1c

File tree

4 files changed

+36
-29
lines changed

4 files changed

+36
-29
lines changed

src/compiler/checker.ts

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1799,27 +1799,37 @@ module ts {
17991799

18001800
function resolveAnonymousTypeMembers(type: ObjectType) {
18011801
var symbol = type.symbol;
1802-
var members = emptySymbols;
1803-
var callSignatures = emptyArray;
1804-
var constructSignatures = emptyArray;
1805-
if (symbol.flags & SymbolFlags.HasExports) {
1806-
members = symbol.exports;
1807-
}
1808-
if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method)) {
1809-
callSignatures = getSignaturesOfSymbol(symbol);
1802+
if (symbol.flags & SymbolFlags.TypeLiteral) {
1803+
// Type literal
1804+
var members = symbol.members;
1805+
var callSignatures = getSignaturesOfSymbol(members["__call"]);
1806+
var constructSignatures = getSignaturesOfSymbol(members["__new"]);
1807+
var stringIndexType = getIndexTypeOfSymbol(symbol, IndexKind.String);
1808+
var numberIndexType = getIndexTypeOfSymbol(symbol, IndexKind.Number);
18101809
}
1811-
if (symbol.flags & SymbolFlags.Class) {
1812-
var classType = getDeclaredTypeOfClass(symbol);
1813-
constructSignatures = getSignaturesOfSymbol(symbol.members["__constructor"]);
1814-
if (!constructSignatures.length) constructSignatures = getDefaultConstructSignatures(classType);
1815-
if (classType.baseTypes.length) {
1816-
var members = createSymbolTable(getNamedMembers(members));
1817-
addInheritedMembers(members, getPropertiesOfType(getTypeOfSymbol(classType.baseTypes[0].symbol)));
1810+
else {
1811+
// Combinations of function, class, enum and module
1812+
var members = emptySymbols;
1813+
var callSignatures = <Signature[]>emptyArray;
1814+
var constructSignatures = <Signature[]>emptyArray;
1815+
if (symbol.flags & SymbolFlags.HasExports) {
1816+
members = symbol.exports;
1817+
}
1818+
if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method)) {
1819+
callSignatures = getSignaturesOfSymbol(symbol);
18181820
}
1821+
if (symbol.flags & SymbolFlags.Class) {
1822+
var classType = getDeclaredTypeOfClass(symbol);
1823+
constructSignatures = getSignaturesOfSymbol(symbol.members["__constructor"]);
1824+
if (!constructSignatures.length) constructSignatures = getDefaultConstructSignatures(classType);
1825+
if (classType.baseTypes.length) {
1826+
var members = createSymbolTable(getNamedMembers(members));
1827+
addInheritedMembers(members, getPropertiesOfType(getTypeOfSymbol(classType.baseTypes[0].symbol)));
1828+
}
1829+
}
1830+
var numberIndexType = (symbol.flags & SymbolFlags.Enum) ? <Type>stringType : undefined;
18191831
}
1820-
var numberIndexType = (symbol.flags & SymbolFlags.Enum) ? stringType : undefined;
1821-
1822-
setObjectTypeMembers(type, members, callSignatures, constructSignatures, /* stringIndexType */ undefined, numberIndexType);
1832+
setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexType, numberIndexType);
18231833
}
18241834

18251835
function resolveObjectTypeMembers(type: ObjectType): ResolvedObjectType {
@@ -2275,13 +2285,8 @@ module ts {
22752285
function getTypeFromTypeLiteralNode(node: TypeLiteralNode): Type {
22762286
var links = getNodeLinks(node);
22772287
if (!links.resolvedType) {
2278-
var symbol = node.symbol;
2279-
var members = symbol.members;
2280-
var callSignatures = getSignaturesOfSymbol(members["__call"]);
2281-
var constructSignatures = getSignaturesOfSymbol(members["__new"]);
2282-
var stringIndexType = getIndexTypeOfSymbol(symbol, IndexKind.String);
2283-
var numberIndexType = getIndexTypeOfSymbol(symbol, IndexKind.Number);
2284-
links.resolvedType = createAnonymousType(symbol, members, callSignatures, constructSignatures, stringIndexType, numberIndexType);
2288+
// Deferred resolution of members is handled by resolveObjectTypeMembers
2289+
links.resolvedType = createObjectType(TypeFlags.Anonymous, node.symbol);
22852290
}
22862291
return links.resolvedType;
22872292
}

tests/baselines/reference/declFileTypeofFunction.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ declare function f(n: typeof f): string;
6868
declare function f(n: typeof g): string;
6969
declare function g(n: typeof g): number;
7070
declare function g(n: typeof f): number;
71-
declare var b: any;
71+
declare var b: () => any;
7272
declare function b1(): typeof b1;
7373
declare function foo(): typeof foo;
7474
declare var foo1: typeof foo;

tests/baselines/reference/declFileTypeofFunction.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ function g() { return undefined; }
2929
>undefined : undefined
3030

3131
var b: () => typeof b;
32-
>b : any
33-
>b : any
32+
>b : () => any
33+
>b : () => any
3434

3535
function b1() {
3636
>b1 : () => typeof b1

tests/baselines/reference/recursiveFunctionTypes.errors.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
==== tests/cases/compiler/recursiveFunctionTypes.ts (12 errors) ====
1+
==== tests/cases/compiler/recursiveFunctionTypes.ts (13 errors) ====
22
function fn(): typeof fn { return 1; }
33
~
44
!!! Type 'number' is not assignable to type '() => typeof fn'.
@@ -39,6 +39,8 @@
3939

4040
var f4: () => typeof f4;
4141
f4 = 3; // error
42+
~~
43+
!!! Type 'number' is not assignable to type '() => any'.
4244

4345
function f5() { return f5; }
4446

0 commit comments

Comments
 (0)