Skip to content

Commit e22500d

Browse files
committed
Merge pull request #824 from Microsoft/unionTypes
Union Types
2 parents 63c0a88 + f5cd414 commit e22500d

File tree

224 files changed

+4960
-4798
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

224 files changed

+4960
-4798
lines changed

src/compiler/checker.ts

+851-263
Large diffs are not rendered by default.

src/compiler/core.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ module ts {
8282
return array1.concat(array2);
8383
}
8484

85-
export function uniqueElements<T>(array: T[]): T[] {
85+
export function deduplicate<T>(array: T[]): T[] {
8686
if (array) {
8787
var result: T[] = [];
8888
for (var i = 0, len = array.length; i < len; i++) {

src/compiler/diagnosticInformationMap.generated.ts

-2
Original file line numberDiff line numberDiff line change
@@ -181,8 +181,6 @@ module ts {
181181
The_right_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type: { code: 2363, category: DiagnosticCategory.Error, key: "The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type." },
182182
Invalid_left_hand_side_of_assignment_expression: { code: 2364, category: DiagnosticCategory.Error, key: "Invalid left-hand side of assignment expression." },
183183
Operator_0_cannot_be_applied_to_types_1_and_2: { code: 2365, category: DiagnosticCategory.Error, key: "Operator '{0}' cannot be applied to types '{1}' and '{2}'." },
184-
No_best_common_type_exists_between_0_1_and_2: { code: 2366, category: DiagnosticCategory.Error, key: "No best common type exists between '{0}', '{1}', and '{2}'." },
185-
No_best_common_type_exists_between_0_and_1: { code: 2367, category: DiagnosticCategory.Error, key: "No best common type exists between '{0}' and '{1}'." },
186184
Type_parameter_name_cannot_be_0: { code: 2368, category: DiagnosticCategory.Error, key: "Type parameter name cannot be '{0}'" },
187185
A_parameter_property_is_only_allowed_in_a_constructor_implementation: { code: 2369, category: DiagnosticCategory.Error, key: "A parameter property is only allowed in a constructor implementation." },
188186
A_rest_parameter_must_be_of_an_array_type: { code: 2370, category: DiagnosticCategory.Error, key: "A rest parameter must be of an array type." },

src/compiler/diagnosticMessages.json

-8
Original file line numberDiff line numberDiff line change
@@ -716,14 +716,6 @@
716716
"category": "Error",
717717
"code": 2365
718718
},
719-
"No best common type exists between '{0}', '{1}', and '{2}'.": {
720-
"category": "Error",
721-
"code": 2366
722-
},
723-
"No best common type exists between '{0}' and '{1}'.": {
724-
"category": "Error",
725-
"code": 2367
726-
},
727719
"Type parameter name cannot be '{0}'": {
728720
"category": "Error",
729721
"code": 2368

src/compiler/parser.ts

+20-2
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,8 @@ module ts {
225225
return child((<ArrayTypeNode>node).elementType);
226226
case SyntaxKind.TupleType:
227227
return children((<TupleTypeNode>node).elementTypes);
228+
case SyntaxKind.UnionType:
229+
return children((<UnionTypeNode>node).types);
228230
case SyntaxKind.ArrayLiteral:
229231
return children((<ArrayLiteral>node).elements);
230232
case SyntaxKind.ObjectLiteral:
@@ -1729,9 +1731,9 @@ module ts {
17291731
}
17301732
}
17311733

1732-
function parseType(): TypeNode {
1734+
function parseNonUnionType(): TypeNode {
17331735
var type = parseNonArrayType();
1734-
while (type && !scanner.hasPrecedingLineBreak() && parseOptional(SyntaxKind.OpenBracketToken)) {
1736+
while (!scanner.hasPrecedingLineBreak() && parseOptional(SyntaxKind.OpenBracketToken)) {
17351737
parseExpected(SyntaxKind.CloseBracketToken);
17361738
var node = <ArrayTypeNode>createNode(SyntaxKind.ArrayType, type.pos);
17371739
node.elementType = type;
@@ -1740,6 +1742,22 @@ module ts {
17401742
return type;
17411743
}
17421744

1745+
function parseType(): TypeNode {
1746+
var type = parseNonUnionType();
1747+
if (token === SyntaxKind.BarToken) {
1748+
var types = <NodeArray<TypeNode>>[type];
1749+
types.pos = type.pos;
1750+
while (parseOptional(SyntaxKind.BarToken)) {
1751+
types.push(parseNonUnionType());
1752+
}
1753+
types.end = getNodeEnd();
1754+
var node = <UnionTypeNode>createNode(SyntaxKind.UnionType, type.pos);
1755+
node.types = types;
1756+
type = finishNode(node);
1757+
}
1758+
return type;
1759+
}
1760+
17431761
function parseTypeAnnotation(): TypeNode {
17441762
return parseOptional(SyntaxKind.ColonToken) ? parseType() : undefined;
17451763
}

src/compiler/types.ts

+44-27
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@ module ts {
154154
TypeLiteral,
155155
ArrayType,
156156
TupleType,
157+
UnionType,
157158
// Expression
158159
ArrayLiteral,
159160
ObjectLiteral,
@@ -224,7 +225,7 @@ module ts {
224225
FirstFutureReservedWord = ImplementsKeyword,
225226
LastFutureReservedWord = YieldKeyword,
226227
FirstTypeNode = TypeReference,
227-
LastTypeNode = TupleType,
228+
LastTypeNode = UnionType,
228229
FirstPunctuation = OpenBraceToken,
229230
LastPunctuation = CaretEqualsToken,
230231
FirstToken = EndOfFileToken,
@@ -337,6 +338,10 @@ module ts {
337338
elementTypes: NodeArray<TypeNode>;
338339
}
339340

341+
export interface UnionTypeNode extends TypeNode {
342+
types: NodeArray<TypeNode>;
343+
}
344+
340345
export interface StringLiteralTypeNode extends TypeNode {
341346
text: string;
342347
}
@@ -648,7 +653,7 @@ module ts {
648653
writeSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): void;
649654
getFullyQualifiedName(symbol: Symbol): string;
650655
getAugmentedPropertiesOfApparentType(type: Type): Symbol[];
651-
getRootSymbol(symbol: Symbol): Symbol;
656+
getRootSymbols(symbol: Symbol): Symbol[];
652657
getContextualType(node: Node): Type;
653658
getResolvedSignature(node: CallExpression, candidatesOutArray?: Signature[]): Signature;
654659
getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature;
@@ -757,19 +762,22 @@ module ts {
757762
ConstructSignature = 0x00010000, // Construct signature
758763
IndexSignature = 0x00020000, // Index signature
759764
TypeParameter = 0x00040000, // Type parameter
765+
UnionProperty = 0x00080000, // Property in union type
760766

761767
// Export markers (see comment in declareModuleMember in binder)
762-
ExportValue = 0x00080000, // Exported value marker
763-
ExportType = 0x00100000, // Exported type marker
764-
ExportNamespace = 0x00200000, // Exported namespace marker
765-
766-
Import = 0x00400000, // Import
767-
Instantiated = 0x00800000, // Instantiated symbol
768-
Merged = 0x01000000, // Merged symbol (created during program binding)
769-
Transient = 0x02000000, // Transient symbol (created during type check)
770-
Prototype = 0x04000000, // Symbol for the prototype property (without source code representation)
771-
772-
Value = Variable | Property | EnumMember | Function | Class | Enum | ValueModule | Method | GetAccessor | SetAccessor,
768+
ExportValue = 0x00100000, // Exported value marker
769+
ExportType = 0x00200000, // Exported type marker
770+
ExportNamespace = 0x00400000, // Exported namespace marker
771+
772+
Import = 0x00800000, // Import
773+
Instantiated = 0x01000000, // Instantiated symbol
774+
Merged = 0x02000000, // Merged symbol (created during program binding)
775+
Transient = 0x04000000, // Transient symbol (created during type check)
776+
Prototype = 0x08000000, // Prototype property (no source representation)
777+
Undefined = 0x10000000, // Symbol for the undefined
778+
779+
Value = Variable | Property | EnumMember | Function | Class | Enum | ValueModule | Method | GetAccessor | SetAccessor | UnionProperty,
780+
773781
Type = Class | Interface | Enum | TypeLiteral | ObjectLiteral | TypeParameter,
774782
Namespace = ValueModule | NamespaceModule,
775783
Module = ValueModule | NamespaceModule,
@@ -827,6 +835,7 @@ module ts {
827835
mapper?: TypeMapper; // Type mapper for instantiation alias
828836
referenced?: boolean; // True if alias symbol has been referenced as a value
829837
exportAssignSymbol?: Symbol; // Symbol exported from external module
838+
unionType?: UnionType; // Containing union type for union property
830839
}
831840

832841
export interface TransientSymbol extends Symbol, SymbolLinks { }
@@ -849,14 +858,15 @@ module ts {
849858
}
850859

851860
export interface NodeLinks {
852-
resolvedType?: Type; // Cached type of type node
853-
resolvedSignature?: Signature; // Cached signature of signature node or call expression
854-
resolvedSymbol?: Symbol; // Cached name resolution result
855-
flags?: NodeCheckFlags; // Set of flags specific to Node
856-
enumMemberValue?: number; // Constant value of enum member
861+
resolvedType?: Type; // Cached type of type node
862+
resolvedSignature?: Signature; // Cached signature of signature node or call expression
863+
resolvedSymbol?: Symbol; // Cached name resolution result
864+
flags?: NodeCheckFlags; // Set of flags specific to Node
865+
enumMemberValue?: number; // Constant value of enum member
857866
isIllegalTypeReferenceInConstraint?: boolean; // Is type reference in constraint refers to the type parameter from the same list
858-
isVisible?: boolean; // Is this node visible
859-
localModuleName?: string; // Local name for module instance
867+
isVisible?: boolean; // Is this node visible
868+
localModuleName?: string; // Local name for module instance
869+
assignmentChecks?: Map<boolean>; // Cache of assignment checks
860870
}
861871

862872
export enum TypeFlags {
@@ -874,13 +884,14 @@ module ts {
874884
Interface = 0x00000800, // Interface
875885
Reference = 0x00001000, // Generic type reference
876886
Tuple = 0x00002000, // Tuple
877-
Anonymous = 0x00004000, // Anonymous
878-
FromSignature = 0x00008000, // Created for signature assignment check
887+
Union = 0x00004000, // Union
888+
Anonymous = 0x00008000, // Anonymous
889+
FromSignature = 0x00010000, // Created for signature assignment check
879890

880-
Intrinsic = Any | String | Number | Boolean | Void | Undefined | Null,
891+
Intrinsic = Any | String | Number | Boolean | Void | Undefined | Null,
881892
StringLike = String | StringLiteral,
882893
NumberLike = Number | Enum,
883-
ObjectType = Class | Interface | Reference | Tuple | Anonymous
894+
ObjectType = Class | Interface | Reference | Tuple | Union | Anonymous,
884895
}
885896

886897
// Properties common to all types
@@ -938,6 +949,10 @@ module ts {
938949
baseArrayType: TypeReference; // Array<T> where T is best common type of element types
939950
}
940951

952+
export interface UnionType extends ObjectType {
953+
types: Type[]; // Constituent types
954+
}
955+
941956
// Resolved object type
942957
export interface ResolvedObjectType extends ObjectType {
943958
members: SymbolTable; // Properties by name
@@ -970,6 +985,7 @@ module ts {
970985
hasStringLiterals: boolean; // True if specialized
971986
target?: Signature; // Instantiation target
972987
mapper?: TypeMapper; // Instantiation mapper
988+
unionSignatures?: Signature[]; // Underlying signatures of a union signature
973989
erasedSignatureCache?: Signature; // Erased version of signature (deferred)
974990
isolatedSignatureType?: ObjectType; // A manufactured type that just contains the signature for purposes of signature comparison
975991
}
@@ -984,9 +1000,10 @@ module ts {
9841000
}
9851001

9861002
export interface InferenceContext {
987-
typeParameters: TypeParameter[];
988-
inferences: Type[][];
989-
inferredTypes: Type[];
1003+
typeParameters: TypeParameter[]; // Type parameters for which inferences are made
1004+
inferenceCount: number; // Incremented for every inference made (whether new or not)
1005+
inferences: Type[][]; // Inferences made for each type parameter
1006+
inferredTypes: Type[]; // Inferred type for each type parameter
9901007
}
9911008

9921009
export interface DiagnosticMessage {

0 commit comments

Comments
 (0)