Skip to content

Commit 8f29661

Browse files
committed
Implementation of Type Aliases in compiler core
1 parent 051478d commit 8f29661

8 files changed

+99
-13
lines changed

src/compiler/binder.ts

+3
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,9 @@ module ts {
326326
case SyntaxKind.InterfaceDeclaration:
327327
bindDeclaration(<Declaration>node, SymbolFlags.Interface, SymbolFlags.InterfaceExcludes);
328328
break;
329+
case SyntaxKind.TypeAliasDeclaration:
330+
bindDeclaration(<Declaration>node, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes);
331+
break;
329332
case SyntaxKind.EnumDeclaration:
330333
bindDeclaration(<Declaration>node, SymbolFlags.Enum, SymbolFlags.EnumExcludes);
331334
break;

src/compiler/checker.ts

+30
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ module ts {
8686
emitFiles: invokeEmitter,
8787
getParentOfSymbol: getParentOfSymbol,
8888
getTypeOfSymbol: getTypeOfSymbol,
89+
getDeclaredTypeOfSymbol: getDeclaredTypeOfSymbol,
8990
getPropertiesOfType: getPropertiesOfType,
9091
getPropertyOfType: getPropertyOfType,
9192
getSignaturesOfType: getSignaturesOfType,
@@ -188,6 +189,7 @@ module ts {
188189
if (flags & SymbolFlags.GetAccessor) result |= SymbolFlags.GetAccessorExcludes;
189190
if (flags & SymbolFlags.SetAccessor) result |= SymbolFlags.SetAccessorExcludes;
190191
if (flags & SymbolFlags.TypeParameter) result |= SymbolFlags.TypeParameterExcludes;
192+
if (flags & SymbolFlags.TypeAlias) result |= SymbolFlags.TypeAliasExcludes;
191193
if (flags & SymbolFlags.Import) result |= SymbolFlags.ImportExcludes;
192194
return result;
193195
}
@@ -1907,6 +1909,24 @@ module ts {
19071909
return <InterfaceType>links.declaredType;
19081910
}
19091911

1912+
function getDeclaredTypeOfTypeAlias(symbol: Symbol): Type {
1913+
var links = getSymbolLinks(symbol);
1914+
if (!links.declaredType) {
1915+
links.declaredType = resolvingType;
1916+
var declaration = <TypeAliasDeclaration>getDeclarationOfKind(symbol, SyntaxKind.TypeAliasDeclaration);
1917+
var type = getTypeFromTypeNode(declaration.type);
1918+
if (links.declaredType === resolvingType) {
1919+
links.declaredType = type;
1920+
}
1921+
}
1922+
else if (links.declaredType === resolvingType) {
1923+
links.declaredType = unknownType;
1924+
var declaration = <TypeAliasDeclaration>getDeclarationOfKind(symbol, SyntaxKind.TypeAliasDeclaration);
1925+
error(declaration.name, Diagnostics.Type_alias_0_circularly_references_itself, symbolToString(symbol));
1926+
}
1927+
return links.declaredType;
1928+
}
1929+
19101930
function getDeclaredTypeOfEnum(symbol: Symbol): Type {
19111931
var links = getSymbolLinks(symbol);
19121932
if (!links.declaredType) {
@@ -1946,6 +1966,9 @@ module ts {
19461966
if (symbol.flags & SymbolFlags.Interface) {
19471967
return getDeclaredTypeOfInterface(symbol);
19481968
}
1969+
if (symbol.flags & SymbolFlags.TypeAlias) {
1970+
return getDeclaredTypeOfTypeAlias(symbol);
1971+
}
19491972
if (symbol.flags & SymbolFlags.Enum) {
19501973
return getDeclaredTypeOfEnum(symbol);
19511974
}
@@ -7304,6 +7327,10 @@ module ts {
73047327
}
73057328
}
73067329

7330+
function checkTypeAliasDeclaration(node: TypeAliasDeclaration) {
7331+
checkSourceElement(node.type);
7332+
}
7333+
73077334
function getConstantValueForExpression(node: Expression): number {
73087335
var isNegative = false;
73097336
if (node.kind === SyntaxKind.PrefixOperator) {
@@ -7596,6 +7623,8 @@ module ts {
75967623
return checkClassDeclaration(<ClassDeclaration>node);
75977624
case SyntaxKind.InterfaceDeclaration:
75987625
return checkInterfaceDeclaration(<InterfaceDeclaration>node);
7626+
case SyntaxKind.TypeAliasDeclaration:
7627+
return checkTypeAliasDeclaration(<TypeAliasDeclaration>node);
75997628
case SyntaxKind.EnumDeclaration:
76007629
return checkEnumDeclaration(<EnumDeclaration>node);
76017630
case SyntaxKind.ModuleDeclaration:
@@ -7840,6 +7869,7 @@ module ts {
78407869
case SyntaxKind.TypeParameter:
78417870
case SyntaxKind.ClassDeclaration:
78427871
case SyntaxKind.InterfaceDeclaration:
7872+
case SyntaxKind.TypeAliasDeclaration:
78437873
case SyntaxKind.EnumDeclaration:
78447874
return true;
78457875
}

src/compiler/diagnosticInformationMap.generated.ts

+1
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ module ts {
261261
Property_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses: { code: 2445, category: DiagnosticCategory.Error, key: "Property '{0}' is protected and only accessible within class '{1}' and its subclasses." },
262262
Property_0_is_protected_and_only_accessible_through_an_instance_of_class_1: { code: 2446, category: DiagnosticCategory.Error, key: "Property '{0}' is protected and only accessible through an instance of class '{1}'." },
263263
The_0_operator_is_not_allowed_for_boolean_types_Consider_using_1_instead: { code: 2447, category: DiagnosticCategory.Error, key: "The '{0}' operator is not allowed for boolean types. Consider using '{1}' instead." },
264+
Type_alias_0_circularly_references_itself: { code: 2448, category: DiagnosticCategory.Error, key: "Type alias '{0}' circularly references itself." },
264265
Import_declaration_0_is_using_private_name_1: { code: 4000, category: DiagnosticCategory.Error, key: "Import declaration '{0}' is using private name '{1}'." },
265266
Type_parameter_0_of_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 4001, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported class has or is using name '{1}' from private module '{2}'." },
266267
Type_parameter_0_of_exported_class_has_or_is_using_private_name_1: { code: 4002, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported class has or is using private name '{1}'." },

src/compiler/diagnosticMessages.json

+4
Original file line numberDiff line numberDiff line change
@@ -1036,6 +1036,10 @@
10361036
"category": "Error",
10371037
"code": 2447
10381038
},
1039+
"Type alias '{0}' circularly references itself.": {
1040+
"category": "Error",
1041+
"code": 2448
1042+
},
10391043

10401044
"Import declaration '{0}' is using private name '{1}'.": {
10411045
"category": "Error",

src/compiler/parser.ts

+22-1
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,9 @@ module ts {
333333
children((<InterfaceDeclaration>node).typeParameters) ||
334334
children((<InterfaceDeclaration>node).baseTypes) ||
335335
children((<InterfaceDeclaration>node).members);
336+
case SyntaxKind.TypeAliasDeclaration:
337+
return child((<TypeAliasDeclaration>node).name) ||
338+
child((<TypeAliasDeclaration>node).type);
336339
case SyntaxKind.EnumDeclaration:
337340
return child((<EnumDeclaration>node).name) ||
338341
children((<EnumDeclaration>node).members);
@@ -478,6 +481,7 @@ module ts {
478481
case SyntaxKind.SetAccessor:
479482
case SyntaxKind.ClassDeclaration:
480483
case SyntaxKind.InterfaceDeclaration:
484+
case SyntaxKind.TypeAliasDeclaration:
481485
case SyntaxKind.EnumDeclaration:
482486
case SyntaxKind.ModuleDeclaration:
483487
case SyntaxKind.ImportDeclaration:
@@ -540,6 +544,7 @@ module ts {
540544
return <ClassDeclaration>node;
541545
case SyntaxKind.EnumDeclaration:
542546
case SyntaxKind.InterfaceDeclaration:
547+
case SyntaxKind.TypeAliasDeclaration:
543548
case SyntaxKind.ModuleDeclaration:
544549
case SyntaxKind.ImportDeclaration:
545550
// early exit cases - declarations cannot be nested in classes
@@ -3075,6 +3080,7 @@ module ts {
30753080
case SyntaxKind.ClassKeyword:
30763081
case SyntaxKind.ModuleKeyword:
30773082
case SyntaxKind.EnumKeyword:
3083+
case SyntaxKind.TypeKeyword:
30783084
// When followed by an identifier, these do not start a statement but might
30793085
// instead be following declarations
30803086
if (isDeclaration()) {
@@ -3626,7 +3632,18 @@ module ts {
36263632
}
36273633
return finishNode(node);
36283634
}
3629-
3635+
3636+
function parseTypeAliasDeclaration(pos: number, flags: NodeFlags): TypeAliasDeclaration {
3637+
var node = <TypeAliasDeclaration>createNode(SyntaxKind.TypeAliasDeclaration, pos);
3638+
node.flags = flags;
3639+
parseExpected(SyntaxKind.TypeKeyword);
3640+
node.name = parseIdentifier();
3641+
parseExpected(SyntaxKind.EqualsToken);
3642+
node.type = parseType();
3643+
parseSemicolon();
3644+
return finishNode(node);
3645+
}
3646+
36303647
function parseAndCheckEnumDeclaration(pos: number, flags: NodeFlags): EnumDeclaration {
36313648
function isIntegerLiteral(expression: Expression): boolean {
36323649
function isInteger(literalExpression: LiteralExpression): boolean {
@@ -3786,6 +3803,7 @@ module ts {
37863803
case SyntaxKind.InterfaceKeyword:
37873804
case SyntaxKind.EnumKeyword:
37883805
case SyntaxKind.ImportKeyword:
3806+
case SyntaxKind.TypeKeyword:
37893807
// Not true keywords so ensure an identifier follows
37903808
return lookAhead(() => nextToken() >= SyntaxKind.Identifier);
37913809
case SyntaxKind.ModuleKeyword:
@@ -3841,6 +3859,9 @@ module ts {
38413859
case SyntaxKind.InterfaceKeyword:
38423860
result = parseInterfaceDeclaration(pos, flags);
38433861
break;
3862+
case SyntaxKind.TypeKeyword:
3863+
result = parseTypeAliasDeclaration(pos, flags);
3864+
break;
38443865
case SyntaxKind.EnumKeyword:
38453866
result = parseAndCheckEnumDeclaration(pos, flags);
38463867
break;

src/compiler/scanner.ts

+1
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ module ts {
8080
"throw": SyntaxKind.ThrowKeyword,
8181
"true": SyntaxKind.TrueKeyword,
8282
"try": SyntaxKind.TryKeyword,
83+
"type": SyntaxKind.TypeKeyword,
8384
"typeof": SyntaxKind.TypeOfKeyword,
8485
"var": SyntaxKind.VarKeyword,
8586
"void": SyntaxKind.VoidKeyword,

src/compiler/types.ts

+20-11
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ module ts {
132132
NumberKeyword,
133133
SetKeyword,
134134
StringKeyword,
135+
TypeKeyword,
135136
// Parse tree nodes
136137
Missing,
137138
// Names
@@ -202,6 +203,7 @@ module ts {
202203
FunctionBlock,
203204
ClassDeclaration,
204205
InterfaceDeclaration,
206+
TypeAliasDeclaration,
205207
EnumDeclaration,
206208
ModuleDeclaration,
207209
ModuleBlock,
@@ -518,6 +520,10 @@ module ts {
518520
members: NodeArray<Node>;
519521
}
520522

523+
export interface TypeAliasDeclaration extends Declaration {
524+
type: TypeNode;
525+
}
526+
521527
export interface EnumMember extends Declaration {
522528
initializer?: Expression;
523529
}
@@ -643,6 +649,7 @@ module ts {
643649
emitFiles(targetSourceFile?: SourceFile): EmitResult;
644650
getParentOfSymbol(symbol: Symbol): Symbol;
645651
getTypeOfSymbol(symbol: Symbol): Type;
652+
getDeclaredTypeOfSymbol(symbol: Symbol): Type;
646653
getPropertiesOfType(type: Type): Symbol[];
647654
getPropertyOfType(type: Type, propertyName: string): Symbol;
648655
getSignaturesOfType(type: Type, kind: SignatureKind): Signature[];
@@ -780,22 +787,23 @@ module ts {
780787
ConstructSignature = 0x00010000, // Construct signature
781788
IndexSignature = 0x00020000, // Index signature
782789
TypeParameter = 0x00040000, // Type parameter
790+
TypeAlias = 0x00080000, // Type alias
783791

784792
// Export markers (see comment in declareModuleMember in binder)
785-
ExportValue = 0x00080000, // Exported value marker
786-
ExportType = 0x00100000, // Exported type marker
787-
ExportNamespace = 0x00200000, // Exported namespace marker
793+
ExportValue = 0x00100000, // Exported value marker
794+
ExportType = 0x00200000, // Exported type marker
795+
ExportNamespace = 0x00400000, // Exported namespace marker
788796

789-
Import = 0x00400000, // Import
790-
Instantiated = 0x00800000, // Instantiated symbol
791-
Merged = 0x01000000, // Merged symbol (created during program binding)
792-
Transient = 0x02000000, // Transient symbol (created during type check)
793-
Prototype = 0x04000000, // Prototype property (no source representation)
794-
UnionProperty = 0x08000000, // Property in union type
797+
Import = 0x00800000, // Import
798+
Instantiated = 0x01000000, // Instantiated symbol
799+
Merged = 0x02000000, // Merged symbol (created during program binding)
800+
Transient = 0x04000000, // Transient symbol (created during type check)
801+
Prototype = 0x08000000, // Prototype property (no source representation)
802+
UnionProperty = 0x10000000, // Property in union type
795803

796804
Value = Variable | Property | EnumMember | Function | Class | Enum | ValueModule | Method | GetAccessor | SetAccessor,
797805

798-
Type = Class | Interface | Enum | TypeLiteral | ObjectLiteral | TypeParameter,
806+
Type = Class | Interface | Enum | TypeLiteral | ObjectLiteral | TypeParameter | TypeAlias,
799807
Namespace = ValueModule | NamespaceModule,
800808
Module = ValueModule | NamespaceModule,
801809
Accessor = GetAccessor | SetAccessor,
@@ -815,11 +823,12 @@ module ts {
815823
GetAccessorExcludes = Value & ~SetAccessor,
816824
SetAccessorExcludes = Value & ~GetAccessor,
817825
TypeParameterExcludes = Type & ~TypeParameter,
826+
TypeAliasExcludes = Type,
818827

819828
// Imports collide with all other imports with the same name.
820829
ImportExcludes = Import,
821830

822-
ModuleMember = Variable | Function | Class | Interface | Enum | Module | Import,
831+
ModuleMember = Variable | Function | Class | Interface | Enum | Module | TypeAlias | Import,
823832

824833
ExportHasLocal = Function | Class | Enum | ValueModule,
825834

src/services/services.ts

+18-1
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,7 @@ module ts {
706706

707707
case SyntaxKind.ClassDeclaration:
708708
case SyntaxKind.InterfaceDeclaration:
709+
case SyntaxKind.TypeAliasDeclaration:
709710
case SyntaxKind.EnumDeclaration:
710711
case SyntaxKind.ModuleDeclaration:
711712
case SyntaxKind.ImportDeclaration:
@@ -1186,6 +1187,9 @@ module ts {
11861187
// interface Y {}
11871188
static interfaceElement = "interface";
11881189

1190+
// type T = ...
1191+
static typeElement = "type";
1192+
11891193
// enum E
11901194
static enumElement = "enum";
11911195

@@ -2695,6 +2699,7 @@ module ts {
26952699

26962700
if (flags & SymbolFlags.Class) return ScriptElementKind.classElement;
26972701
if (flags & SymbolFlags.Enum) return ScriptElementKind.enumElement;
2702+
if (flags & SymbolFlags.TypeAlias) return ScriptElementKind.typeElement;
26982703
if (flags & SymbolFlags.Interface) return ScriptElementKind.interfaceElement;
26992704
if (flags & SymbolFlags.TypeParameter) return ScriptElementKind.typeParameterElement;
27002705

@@ -2763,6 +2768,7 @@ module ts {
27632768
case SyntaxKind.ModuleDeclaration: return ScriptElementKind.moduleElement;
27642769
case SyntaxKind.ClassDeclaration: return ScriptElementKind.classElement;
27652770
case SyntaxKind.InterfaceDeclaration: return ScriptElementKind.interfaceElement;
2771+
case SyntaxKind.TypeAliasDeclaration: return ScriptElementKind.typeElement;
27662772
case SyntaxKind.EnumDeclaration: return ScriptElementKind.enumElement;
27672773
case SyntaxKind.VariableDeclaration: return ScriptElementKind.variableElement;
27682774
case SyntaxKind.FunctionDeclaration: return ScriptElementKind.functionElement;
@@ -2777,8 +2783,8 @@ module ts {
27772783
case SyntaxKind.TypeParameter: return ScriptElementKind.typeParameterElement;
27782784
case SyntaxKind.EnumMember: return ScriptElementKind.variableElement;
27792785
case SyntaxKind.Parameter: return (node.flags & NodeFlags.AccessibilityModifier) ? ScriptElementKind.memberVariableElement : ScriptElementKind.parameterElement;
2780-
return ScriptElementKind.unknown;
27812786
}
2787+
return ScriptElementKind.unknown;
27822788
}
27832789

27842790
function getSymbolModifiers(symbol: Symbol): string {
@@ -2916,6 +2922,16 @@ module ts {
29162922
addFullSymbolName(symbol);
29172923
writeTypeParametersOfSymbol(symbol, sourceFile);
29182924
}
2925+
if (symbolFlags & SymbolFlags.TypeAlias) {
2926+
addNewLineIfDisplayPartsExist();
2927+
displayParts.push(keywordPart(SyntaxKind.TypeKeyword));
2928+
displayParts.push(spacePart());
2929+
addFullSymbolName(symbol);
2930+
displayParts.push(spacePart());
2931+
displayParts.push(punctuationPart(SyntaxKind.EqualsToken));
2932+
displayParts.push(spacePart());
2933+
displayParts.push.apply(displayParts, typeToDisplayParts(typeResolver, typeResolver.getDeclaredTypeOfSymbol(symbol), enclosingDeclaration));
2934+
}
29192935
if (symbolFlags & SymbolFlags.Enum) {
29202936
addNewLineIfDisplayPartsExist();
29212937
displayParts.push(keywordPart(SyntaxKind.EnumKeyword));
@@ -4503,6 +4519,7 @@ module ts {
45034519

45044520
case SyntaxKind.TypeParameter:
45054521
case SyntaxKind.InterfaceDeclaration:
4522+
case SyntaxKind.TypeAliasDeclaration:
45064523
case SyntaxKind.TypeLiteral:
45074524
return SemanticMeaning.Type;
45084525

0 commit comments

Comments
 (0)