mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-27 23:58:38 -06:00
Initial implementation of Union Types
This commit is contained in:
parent
438aa899ea
commit
e836fe1729
@ -130,6 +130,7 @@ module ts {
|
||||
var globalRegExpType: ObjectType;
|
||||
|
||||
var tupleTypes: Map<TupleType> = {};
|
||||
var unionTypes: Map<UnionType> = {};
|
||||
var stringLiteralTypes: Map<StringLiteralType> = {};
|
||||
var emitExtends = false;
|
||||
|
||||
@ -1136,6 +1137,9 @@ module ts {
|
||||
else if (type.flags & TypeFlags.Tuple) {
|
||||
writeTupleType(<TupleType>type);
|
||||
}
|
||||
else if (type.flags & TypeFlags.Union) {
|
||||
writeUnionType(<UnionType>type);
|
||||
}
|
||||
else if (type.flags & TypeFlags.Anonymous) {
|
||||
writeAnonymousType(<ObjectType>type, allowFunctionOrConstructorTypeLiteral);
|
||||
}
|
||||
@ -1153,18 +1157,21 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function writeTypeList(types: Type[]) {
|
||||
function writeTypeList(types: Type[], union?: boolean) {
|
||||
for (var i = 0; i < types.length; i++) {
|
||||
if (i > 0) {
|
||||
writePunctuation(writer, SyntaxKind.CommaToken);
|
||||
if (union) {
|
||||
writeSpace(writer);
|
||||
}
|
||||
writePunctuation(writer, union ? SyntaxKind.BarToken : SyntaxKind.CommaToken);
|
||||
writeSpace(writer);
|
||||
}
|
||||
writeType(types[i], /*allowFunctionOrConstructorTypeLiteral*/ true);
|
||||
writeType(types[i], /*allowFunctionOrConstructorTypeLiteral*/ !union);
|
||||
}
|
||||
}
|
||||
|
||||
function writeTypeReference(type: TypeReference) {
|
||||
if (type.target === globalArrayType && !(flags & TypeFormatFlags.WriteArrayAsGenericType)) {
|
||||
if (type.target === globalArrayType && !(flags & TypeFormatFlags.WriteArrayAsGenericType) && !(type.typeArguments[0].flags & TypeFlags.Union)) {
|
||||
// If we are writing array element type the arrow style signatures are not allowed as
|
||||
// we need to surround it by curlies, e.g. { (): T; }[]; as () => T[] would mean something different
|
||||
writeType(type.typeArguments[0], /*allowFunctionOrConstructorTypeLiteral*/ false);
|
||||
@ -1185,6 +1192,10 @@ module ts {
|
||||
writePunctuation(writer, SyntaxKind.CloseBracketToken);
|
||||
}
|
||||
|
||||
function writeUnionType(type: UnionType) {
|
||||
writeTypeList(type.types, /*union*/ true);
|
||||
}
|
||||
|
||||
function writeAnonymousType(type: ObjectType, allowFunctionOrConstructorTypeLiteral: boolean) {
|
||||
// Always use 'typeof T' for type of class, enum, and module objects
|
||||
if (type.symbol && type.symbol.flags & (SymbolFlags.Class | SymbolFlags.Enum | SymbolFlags.ValueModule)) {
|
||||
@ -1730,6 +1741,15 @@ module ts {
|
||||
return links.type;
|
||||
}
|
||||
|
||||
function getTypeOfUnionProperty(symbol: Symbol): Type {
|
||||
var links = getSymbolLinks(symbol);
|
||||
if (!links.type) {
|
||||
var types = map(links.unionType.types, t => getTypeOfSymbol(getPropertyOfType(getApparentType(t), symbol.name) || undefinedSymbol));
|
||||
links.type = getUnionType(types);
|
||||
}
|
||||
return links.type;
|
||||
}
|
||||
|
||||
function getTypeOfSymbol(symbol: Symbol): Type {
|
||||
if (symbol.flags & (SymbolFlags.Variable | SymbolFlags.Property)) {
|
||||
return getTypeOfVariableOrParameterOrProperty(symbol);
|
||||
@ -1749,6 +1769,9 @@ module ts {
|
||||
if (symbol.flags & SymbolFlags.Instantiated) {
|
||||
return getTypeOfInstantiatedSymbol(symbol);
|
||||
}
|
||||
if (symbol.flags & SymbolFlags.UnionProperty) {
|
||||
return getTypeOfUnionProperty(symbol);
|
||||
}
|
||||
return unknownType;
|
||||
}
|
||||
|
||||
@ -2045,6 +2068,71 @@ module ts {
|
||||
setObjectTypeMembers(type, members, arrayType.callSignatures, arrayType.constructSignatures, arrayType.stringIndexType, arrayType.numberIndexType);
|
||||
}
|
||||
|
||||
function signatureListsIdentical(s: Signature[], t: Signature[]): boolean {
|
||||
if (s.length !== t.length) return false;
|
||||
for (var i = 0; i < s.length; i++) {
|
||||
if (!compareSignatures(s[i], t[i], false, isTypeIdenticalTo)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function getUnionSignatures(types: Type[], kind: SignatureKind): Signature[] {
|
||||
var signatureLists = map(types, t => getSignaturesOfType(t, kind));
|
||||
var baseSignatures = signatureLists[0];
|
||||
for (var i = 0; i < baseSignatures.length; i++) {
|
||||
if (baseSignatures[i].typeParameters) return emptyArray;
|
||||
}
|
||||
for (var i = 1; i < signatureLists.length; i++) {
|
||||
if (!signatureListsIdentical(baseSignatures, signatureLists[i])) return emptyArray;
|
||||
}
|
||||
var result = map(baseSignatures, cloneSignature);
|
||||
for (var i = 0; i < result.length; i++) {
|
||||
var s = result[i];
|
||||
s.resolvedReturnType = undefined;
|
||||
s.unionSignatures = map(signatureLists, signatures => signatures[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function getUnionIndexType(types: Type[], kind: IndexKind): Type {
|
||||
var indexTypes: Type[] = [];
|
||||
for (var i = 0; i < types.length; i++) {
|
||||
var indexType = getIndexTypeOfType(types[i], kind);
|
||||
if (!indexType) return undefined;
|
||||
indexTypes.push(indexType);
|
||||
}
|
||||
return getUnionType(indexTypes);
|
||||
}
|
||||
|
||||
function resolveUnionTypeMembers(type: UnionType) {
|
||||
var types: Type[] = [];
|
||||
forEach(type.types, t => {
|
||||
var apparentType = getApparentType(t);
|
||||
if (!contains(types, apparentType)) {
|
||||
types.push(apparentType);
|
||||
}
|
||||
});
|
||||
if (types.length <= 1) {
|
||||
var res = types.length ? resolveObjectTypeMembers(types[0]) : emptyObjectType;
|
||||
setObjectTypeMembers(type, res.members, res.callSignatures, res.constructSignatures, res.stringIndexType, res.numberIndexType);
|
||||
return;
|
||||
}
|
||||
var members: SymbolTable = {};
|
||||
forEach(getPropertiesOfType(types[0]), prop => {
|
||||
for (var i = 1; i < types.length; i++) {
|
||||
if (!getPropertyOfType(types[i], prop.name)) return;
|
||||
}
|
||||
var symbol = <TransientSymbol>createSymbol(SymbolFlags.UnionProperty | SymbolFlags.Transient, prop.name);
|
||||
symbol.unionType = type;
|
||||
members[prop.name] = symbol;
|
||||
});
|
||||
var callSignatures = getUnionSignatures(types, SignatureKind.Call);
|
||||
var constructSignatures = getUnionSignatures(types, SignatureKind.Construct);
|
||||
var stringIndexType = getUnionIndexType(types, IndexKind.String);
|
||||
var numberIndexType = getUnionIndexType(types, IndexKind.Number);
|
||||
setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexType, numberIndexType);
|
||||
}
|
||||
|
||||
function resolveAnonymousTypeMembers(type: ObjectType) {
|
||||
var symbol = type.symbol;
|
||||
if (symbol.flags & SymbolFlags.TypeLiteral) {
|
||||
@ -2093,6 +2181,9 @@ module ts {
|
||||
else if (type.flags & TypeFlags.Tuple) {
|
||||
resolveTupleTypeMembers(<TupleType>type);
|
||||
}
|
||||
else if (type.flags & TypeFlags.Union) {
|
||||
resolveUnionTypeMembers(<UnionType>type);
|
||||
}
|
||||
else {
|
||||
resolveTypeReferenceMembers(<TypeReference>type);
|
||||
}
|
||||
@ -2253,6 +2344,9 @@ module ts {
|
||||
if (signature.target) {
|
||||
var type = instantiateType(getReturnTypeOfSignature(signature.target), signature.mapper);
|
||||
}
|
||||
else if (signature.unionSignatures) {
|
||||
var type = getUnionType(map(signature.unionSignatures, getReturnTypeOfSignature));
|
||||
}
|
||||
else {
|
||||
var type = getReturnTypeFromBody(<FunctionDeclaration>signature.declaration);
|
||||
}
|
||||
@ -2561,6 +2655,70 @@ module ts {
|
||||
return links.resolvedType;
|
||||
}
|
||||
|
||||
function addTypeToSortedSet(sortedSet: Type[], type: Type) {
|
||||
if (type.flags & TypeFlags.Union) {
|
||||
addTypesToSortedSet(sortedSet, (<UnionType>type).types);
|
||||
}
|
||||
else {
|
||||
var i = 0;
|
||||
var id = type.id;
|
||||
while (i < sortedSet.length && sortedSet[i].id < id) i++;
|
||||
if (i === sortedSet.length || sortedSet[i].id !== id) {
|
||||
sortedSet.splice(i, 0, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function addTypesToSortedSet(sortedTypes: Type[], types: Type[]) {
|
||||
for (var i = 0, len = types.length; i < len; i++) {
|
||||
addTypeToSortedSet(sortedTypes, types[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function isSubtypeOfAny(candidate: Type, types: Type[]): boolean {
|
||||
for (var i = 0, len = types.length; i < len; i++) {
|
||||
if (candidate !== types[i] && isTypeSubtypeOf(candidate, types[i])) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function removeSubtypes(types: Type[]) {
|
||||
var i = types.length;
|
||||
while (i > 0) {
|
||||
i--;
|
||||
if (isSubtypeOfAny(types[i], types)) {
|
||||
types.splice(i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getUnionType(types: Type[]): Type {
|
||||
if (types.length === 0) {
|
||||
return emptyObjectType;
|
||||
}
|
||||
var sortedTypes: Type[] = [];
|
||||
addTypesToSortedSet(sortedTypes, types);
|
||||
removeSubtypes(sortedTypes);
|
||||
if (sortedTypes.length === 1) {
|
||||
return sortedTypes[0];
|
||||
}
|
||||
var id = getTypeListId(sortedTypes);
|
||||
var type = unionTypes[id];
|
||||
if (!type) {
|
||||
type = unionTypes[id] = <UnionType>createObjectType(TypeFlags.Union);
|
||||
type.types = sortedTypes;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
function getTypeFromUnionTypeNode(node: UnionTypeNode): Type {
|
||||
var links = getNodeLinks(node);
|
||||
if (!links.resolvedType) {
|
||||
links.resolvedType = getUnionType(map(node.types, getTypeFromTypeNode));
|
||||
}
|
||||
return links.resolvedType;
|
||||
}
|
||||
|
||||
function getTypeFromTypeLiteralNode(node: TypeLiteralNode): Type {
|
||||
var links = getNodeLinks(node);
|
||||
if (!links.resolvedType) {
|
||||
@ -2607,6 +2765,8 @@ module ts {
|
||||
return getTypeFromArrayTypeNode(<ArrayTypeNode>node);
|
||||
case SyntaxKind.TupleType:
|
||||
return getTypeFromTupleTypeNode(<TupleTypeNode>node);
|
||||
case SyntaxKind.UnionType:
|
||||
return getTypeFromUnionTypeNode(<UnionTypeNode>node);
|
||||
case SyntaxKind.TypeLiteral:
|
||||
return getTypeFromTypeLiteralNode(<TypeLiteralNode>node);
|
||||
// This function assumes that an identifier or qualified name is a type expression
|
||||
@ -2771,6 +2931,9 @@ module ts {
|
||||
if (type.flags & TypeFlags.Tuple) {
|
||||
return createTupleType(instantiateList((<TupleType>type).elementTypes, mapper, instantiateType));
|
||||
}
|
||||
if (type.flags & TypeFlags.Union) {
|
||||
return getUnionType(instantiateList((<UnionType>type).types, mapper, instantiateType));
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
@ -2932,7 +3095,7 @@ module ts {
|
||||
errorInfo = chainDiagnosticMessages(errorInfo, message, arg0, arg1, arg2);
|
||||
}
|
||||
|
||||
function isRelatedTo(source: Type, target: Type, reportErrors: boolean): boolean {
|
||||
function isRelatedTo(source: Type, target: Type, reportErrors?: boolean): boolean {
|
||||
return isRelatedToWithCustomErrors(source, target, reportErrors, /*chainedMessage*/ undefined, /*terminalMessage*/ undefined);
|
||||
}
|
||||
|
||||
@ -2953,8 +3116,17 @@ module ts {
|
||||
if (source === numberType && target.flags & TypeFlags.Enum) return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (source.flags & TypeFlags.TypeParameter && target.flags & TypeFlags.TypeParameter) {
|
||||
if (source.flags & TypeFlags.Union) {
|
||||
if (unionTypeRelatedToType(<UnionType>source, target, reportErrors)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (target.flags & TypeFlags.Union) {
|
||||
if (typeRelatedToUnionType(source, <UnionType>target, reportErrors)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (source.flags & TypeFlags.TypeParameter && target.flags & TypeFlags.TypeParameter) {
|
||||
if (typeParameterRelatedTo(<TypeParameter>source, <TypeParameter>target, reportErrors)) {
|
||||
return true;
|
||||
}
|
||||
@ -2971,7 +3143,7 @@ module ts {
|
||||
// Report structural errors only if we haven't reported any errors yet
|
||||
var reportStructuralErrors = reportErrors && errorInfo === saveErrorInfo;
|
||||
// identity relation does not use apparent type
|
||||
var sourceOrApparentType = relation === identityRelation ? source : getApparentType(source);
|
||||
var sourceOrApparentType = relation === identityRelation ? source : getApparentType(source);
|
||||
if (sourceOrApparentType.flags & TypeFlags.ObjectType && target.flags & TypeFlags.ObjectType &&
|
||||
objectTypeRelatedTo(sourceOrApparentType, <ObjectType>target, reportStructuralErrors)) {
|
||||
errorInfo = saveErrorInfo;
|
||||
@ -2992,6 +3164,26 @@ module ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
function typeRelatedToUnionType(source: Type, target: UnionType, reportErrors: boolean): boolean {
|
||||
var targetTypes = target.types;
|
||||
for (var i = 0, len = targetTypes.length; i < len; i++) {
|
||||
if (isRelatedTo(source, targetTypes[i], reportErrors && i === len - 1)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function unionTypeRelatedToType(source: UnionType, target: Type, reportErrors: boolean): boolean {
|
||||
var sourceTypes = source.types;
|
||||
for (var i = 0, len = sourceTypes.length; i < len; i++) {
|
||||
if (!isRelatedTo(sourceTypes[i], target, reportErrors)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function typesRelatedTo(sources: Type[], targets: Type[], reportErrors: boolean): boolean {
|
||||
for (var i = 0, len = sources.length; i < len; i++) {
|
||||
if (!isRelatedTo(sources[i], targets[i], reportErrors)) return false;
|
||||
@ -3093,34 +3285,12 @@ module ts {
|
||||
|
||||
function propertiesRelatedTo(source: ObjectType, target: ObjectType, reportErrors: boolean): boolean {
|
||||
if (relation === identityRelation) {
|
||||
return propertiesAreIdenticalTo(source, target, reportErrors);
|
||||
return propertiesIdenticalTo(source, target, reportErrors);
|
||||
}
|
||||
else {
|
||||
return propertiesAreSubtypeOrAssignableTo(<ApparentType>source, target, reportErrors);
|
||||
}
|
||||
}
|
||||
|
||||
function propertiesAreIdenticalTo(source: ObjectType, target: ObjectType, reportErrors: boolean): boolean {
|
||||
var sourceProperties = getPropertiesOfType(source);
|
||||
var targetProperties = getPropertiesOfType(target);
|
||||
if (sourceProperties.length !== targetProperties.length) {
|
||||
return false;
|
||||
}
|
||||
for (var i = 0, len = sourceProperties.length; i < len; ++i) {
|
||||
var sourceProp = sourceProperties[i];
|
||||
var targetProp = getPropertyOfType(target, sourceProp.name);
|
||||
if (!targetProp || !isPropertyIdenticalToRecursive(sourceProp, targetProp, reportErrors, isRelatedTo)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function propertiesAreSubtypeOrAssignableTo(source: ApparentType, target: ObjectType, reportErrors: boolean): boolean {
|
||||
var properties = getPropertiesOfType(target);
|
||||
for (var i = 0; i < properties.length; i++) {
|
||||
var targetProp = properties[i];
|
||||
var sourceProp = getPropertyOfApparentType(source, targetProp.name);
|
||||
var sourceProp = getPropertyOfApparentType(<ApparentType>source, targetProp.name);
|
||||
if (sourceProp !== targetProp) {
|
||||
if (!sourceProp) {
|
||||
if (!isOptionalProperty(targetProp)) {
|
||||
@ -3193,80 +3363,26 @@ module ts {
|
||||
return true;
|
||||
}
|
||||
|
||||
function signaturesRelatedTo(source: ObjectType, target: ObjectType, kind: SignatureKind, reportErrors: boolean): boolean {
|
||||
if (relation === identityRelation) {
|
||||
return areSignaturesIdenticalTo(source, target, kind, reportErrors);
|
||||
}
|
||||
else {
|
||||
return areSignaturesSubtypeOrAssignableTo(source, target, kind, reportErrors);
|
||||
}
|
||||
}
|
||||
|
||||
function areSignaturesIdenticalTo(source: ObjectType, target: ObjectType, kind: SignatureKind, reportErrors: boolean): boolean {
|
||||
var sourceSignatures = getSignaturesOfType(source, kind);
|
||||
var targetSignatures = getSignaturesOfType(target, kind);
|
||||
if (sourceSignatures.length !== targetSignatures.length) {
|
||||
function propertiesIdenticalTo(source: ObjectType, target: ObjectType, reportErrors: boolean): boolean {
|
||||
var sourceProperties = getPropertiesOfType(source);
|
||||
var targetProperties = getPropertiesOfType(target);
|
||||
if (sourceProperties.length !== targetProperties.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (var i = 0, len = sourceSignatures.length; i < len; ++i) {
|
||||
if (!isSignatureIdenticalTo(sourceSignatures[i], targetSignatures[i], reportErrors)) {
|
||||
for (var i = 0, len = sourceProperties.length; i < len; ++i) {
|
||||
var sourceProp = sourceProperties[i];
|
||||
var targetProp = getPropertyOfType(target, sourceProp.name);
|
||||
if (!targetProp || !isPropertyIdenticalToRecursive(sourceProp, targetProp, reportErrors, isRelatedTo)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function isSignatureIdenticalTo(source: Signature, target: Signature, reportErrors: boolean): boolean {
|
||||
if (source === target) {
|
||||
return true;
|
||||
function signaturesRelatedTo(source: ObjectType, target: ObjectType, kind: SignatureKind, reportErrors: boolean): boolean {
|
||||
if (relation === identityRelation) {
|
||||
return signaturesIdenticalTo(source, target, kind, reportErrors);
|
||||
}
|
||||
|
||||
if (source.hasRestParameter !== target.hasRestParameter) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (source.parameters.length !== target.parameters.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (source.minArgumentCount !== target.minArgumentCount) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (source.typeParameters && target.typeParameters) {
|
||||
if (source.typeParameters.length !== target.typeParameters.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (var i = 0, len = source.typeParameters.length; i < len; ++i) {
|
||||
if (!isRelatedTo(source.typeParameters[i], target.typeParameters[i], reportErrors)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (source.typeParameters || source.typeParameters) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Spec 1.0 Section 3.8.3 & 3.8.4:
|
||||
// M and N (the signatures) are instantiated using type Any as the type argument for all type parameters declared by M and N
|
||||
source = getErasedSignature(source);
|
||||
target = getErasedSignature(target);
|
||||
for (var i = 0, len = source.parameters.length; i < len; i++) {
|
||||
var s = source.hasRestParameter && i === len - 1 ? getRestTypeOfSignature(source) : getTypeOfSymbol(source.parameters[i]);
|
||||
var t = target.hasRestParameter && i === len - 1 ? getRestTypeOfSignature(target) : getTypeOfSymbol(target.parameters[i]);
|
||||
if (!isRelatedTo(s, t, reportErrors)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
var t = getReturnTypeOfSignature(target);
|
||||
var s = getReturnTypeOfSignature(source);
|
||||
return isRelatedTo(s, t, reportErrors);
|
||||
}
|
||||
|
||||
function areSignaturesSubtypeOrAssignableTo(source: ObjectType, target: ObjectType, kind: SignatureKind, reportErrors: boolean): boolean {
|
||||
if (target === anyFunctionType || source === anyFunctionType) return true;
|
||||
var sourceSignatures = getSignaturesOfType(source, kind);
|
||||
var targetSignatures = getSignaturesOfType(target, kind);
|
||||
@ -3278,7 +3394,7 @@ module ts {
|
||||
for (var j = 0; j < sourceSignatures.length; j++) {
|
||||
var s = sourceSignatures[j];
|
||||
if (!s.hasStringLiterals || source.flags & TypeFlags.FromSignature) {
|
||||
if (isSignatureSubtypeOrAssignableTo(s, t, localErrors)) {
|
||||
if (signatureRelatedTo(s, t, localErrors)) {
|
||||
errorInfo = saveErrorInfo;
|
||||
continue outer;
|
||||
}
|
||||
@ -3292,15 +3408,13 @@ module ts {
|
||||
return true;
|
||||
}
|
||||
|
||||
function isSignatureSubtypeOrAssignableTo(source: Signature, target: Signature, reportErrors: boolean): boolean {
|
||||
function signatureRelatedTo(source: Signature, target: Signature, reportErrors: boolean): boolean {
|
||||
if (source === target) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!target.hasRestParameter && source.minArgumentCount > target.parameters.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
var sourceMax = source.parameters.length;
|
||||
var targetMax = target.parameters.length;
|
||||
var checkCount: number;
|
||||
@ -3346,71 +3460,117 @@ module ts {
|
||||
return isRelatedTo(s, t, reportErrors);
|
||||
}
|
||||
|
||||
function signaturesIdenticalTo(source: ObjectType, target: ObjectType, kind: SignatureKind, reportErrors: boolean): boolean {
|
||||
var sourceSignatures = getSignaturesOfType(source, kind);
|
||||
var targetSignatures = getSignaturesOfType(target, kind);
|
||||
if (sourceSignatures.length !== targetSignatures.length) {
|
||||
return false;
|
||||
}
|
||||
for (var i = 0, len = sourceSignatures.length; i < len; ++i) {
|
||||
if (!compareSignatures(sourceSignatures[i], targetSignatures[i], /*returnTypes*/ true, isRelatedTo)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function stringIndexTypesRelatedTo(source: ObjectType, target: ObjectType, reportErrors: boolean): boolean {
|
||||
if (relation === identityRelation) {
|
||||
return areIndexTypesIdenticalTo(IndexKind.String, source, target, reportErrors);
|
||||
return indexTypesIdenticalTo(IndexKind.String, source, target, reportErrors);
|
||||
}
|
||||
else {
|
||||
var targetType = getIndexTypeOfType(target, IndexKind.String);
|
||||
if (targetType) {
|
||||
var sourceType = getIndexTypeOfType(source, IndexKind.String);
|
||||
if (!sourceType) {
|
||||
if (reportErrors) {
|
||||
reportError(Diagnostics.Index_signature_is_missing_in_type_0, typeToString(source));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (!isRelatedTo(sourceType, targetType, reportErrors)) {
|
||||
if (reportErrors) {
|
||||
reportError(Diagnostics.Index_signatures_are_incompatible_Colon);
|
||||
}
|
||||
return false;
|
||||
var targetType = getIndexTypeOfType(target, IndexKind.String);
|
||||
if (targetType) {
|
||||
var sourceType = getIndexTypeOfType(source, IndexKind.String);
|
||||
if (!sourceType) {
|
||||
if (reportErrors) {
|
||||
reportError(Diagnostics.Index_signature_is_missing_in_type_0, typeToString(source));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (!isRelatedTo(sourceType, targetType, reportErrors)) {
|
||||
if (reportErrors) {
|
||||
reportError(Diagnostics.Index_signatures_are_incompatible_Colon);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function numberIndexTypesRelatedTo(source: ObjectType, target: ObjectType, reportErrors: boolean): boolean {
|
||||
if (relation === identityRelation) {
|
||||
return areIndexTypesIdenticalTo(IndexKind.Number, source, target, reportErrors);
|
||||
return indexTypesIdenticalTo(IndexKind.Number, source, target, reportErrors);
|
||||
}
|
||||
else {
|
||||
var targetType = getIndexTypeOfType(target, IndexKind.Number);
|
||||
if (targetType) {
|
||||
var sourceStringType = getIndexTypeOfType(source, IndexKind.String);
|
||||
var sourceNumberType = getIndexTypeOfType(source, IndexKind.Number);
|
||||
if (!(sourceStringType || sourceNumberType)) {
|
||||
if (reportErrors) {
|
||||
reportError(Diagnostics.Index_signature_is_missing_in_type_0, typeToString(source));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (sourceStringType && sourceNumberType) {
|
||||
// If we know for sure we're testing both string and numeric index types then only report errors from the second one
|
||||
var compatible = isRelatedTo(sourceStringType, targetType, false) || isRelatedTo(sourceNumberType, targetType, reportErrors);
|
||||
}
|
||||
else {
|
||||
var compatible = isRelatedTo(sourceStringType || sourceNumberType, targetType, reportErrors);
|
||||
}
|
||||
if (!compatible) {
|
||||
if (reportErrors) {
|
||||
reportError(Diagnostics.Index_signatures_are_incompatible_Colon);
|
||||
}
|
||||
return false;
|
||||
var targetType = getIndexTypeOfType(target, IndexKind.Number);
|
||||
if (targetType) {
|
||||
var sourceStringType = getIndexTypeOfType(source, IndexKind.String);
|
||||
var sourceNumberType = getIndexTypeOfType(source, IndexKind.Number);
|
||||
if (!(sourceStringType || sourceNumberType)) {
|
||||
if (reportErrors) {
|
||||
reportError(Diagnostics.Index_signature_is_missing_in_type_0, typeToString(source));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (sourceStringType && sourceNumberType) {
|
||||
// If we know for sure we're testing both string and numeric index types then only report errors from the second one
|
||||
var compatible = isRelatedTo(sourceStringType, targetType, false) || isRelatedTo(sourceNumberType, targetType, reportErrors);
|
||||
}
|
||||
else {
|
||||
var compatible = isRelatedTo(sourceStringType || sourceNumberType, targetType, reportErrors);
|
||||
}
|
||||
if (!compatible) {
|
||||
if (reportErrors) {
|
||||
reportError(Diagnostics.Index_signatures_are_incompatible_Colon);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function areIndexTypesIdenticalTo(indexKind: IndexKind, source: ObjectType, target: ObjectType, reportErrors: boolean): boolean {
|
||||
function indexTypesIdenticalTo(indexKind: IndexKind, source: ObjectType, target: ObjectType, reportErrors: boolean): boolean {
|
||||
var targetType = getIndexTypeOfType(target, indexKind);
|
||||
var sourceType = getIndexTypeOfType(source, indexKind);
|
||||
return (!sourceType && !targetType) || (sourceType && targetType && isRelatedTo(sourceType, targetType, reportErrors));
|
||||
}
|
||||
}
|
||||
|
||||
function compareSignatures(source: Signature, target: Signature, returnTypes: boolean, compareTypes: (s: Type, t: Type) => boolean): boolean {
|
||||
if (source === target) {
|
||||
return true;
|
||||
}
|
||||
if (source.parameters.length !== target.parameters.length ||
|
||||
source.minArgumentCount !== target.minArgumentCount ||
|
||||
source.hasRestParameter !== target.hasRestParameter) {
|
||||
return false;
|
||||
}
|
||||
if (source.typeParameters && target.typeParameters) {
|
||||
if (source.typeParameters.length !== target.typeParameters.length) {
|
||||
return false;
|
||||
}
|
||||
for (var i = 0, len = source.typeParameters.length; i < len; ++i) {
|
||||
if (!compareTypes(source.typeParameters[i], target.typeParameters[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (source.typeParameters || source.typeParameters) {
|
||||
return false;
|
||||
}
|
||||
// Spec 1.0 Section 3.8.3 & 3.8.4:
|
||||
// M and N (the signatures) are instantiated using type Any as the type argument for all type parameters declared by M and N
|
||||
source = getErasedSignature(source);
|
||||
target = getErasedSignature(target);
|
||||
for (var i = 0, len = source.parameters.length; i < len; i++) {
|
||||
var s = source.hasRestParameter && i === len - 1 ? getRestTypeOfSignature(source) : getTypeOfSymbol(source.parameters[i]);
|
||||
var t = target.hasRestParameter && i === len - 1 ? getRestTypeOfSignature(target) : getTypeOfSymbol(target.parameters[i]);
|
||||
if (!compareTypes(s, t)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return !returnTypes || compareTypes(getReturnTypeOfSignature(source), getReturnTypeOfSignature(target));
|
||||
}
|
||||
|
||||
function isSupertypeOfEach(candidate: Type, types: Type[]): boolean {
|
||||
for (var i = 0, len = types.length; i < len; i++) {
|
||||
if (candidate !== types[i] && !isTypeSubtypeOf(types[i], candidate)) return false;
|
||||
@ -3418,11 +3578,13 @@ module ts {
|
||||
return true;
|
||||
}
|
||||
|
||||
function getBestCommonType(types: Type[], contextualType?: Type, candidatesOnly?: boolean): Type {
|
||||
if (contextualType && isSupertypeOfEach(contextualType, types)) return contextualType;
|
||||
return forEach(types, t => isSupertypeOfEach(t, types) ? t : undefined) || (candidatesOnly ? undefined : emptyObjectType);
|
||||
function getCommonSupertype(types: Type[]): Type {
|
||||
return forEach(types, t => isSupertypeOfEach(t, types) ? t : undefined);
|
||||
}
|
||||
|
||||
function getBestCommonType(types: Type[], contextualType?: Type): Type {
|
||||
return contextualType && isSupertypeOfEach(contextualType, types) ? contextualType : getUnionType(types);
}
|
||||
|
||||
function isTypeOfObjectLiteral(type: Type): boolean {
|
||||
return (type.flags & TypeFlags.Anonymous) && type.symbol && (type.symbol.flags & SymbolFlags.ObjectLiteral) ? true : false;
|
||||
}
|
||||
@ -3439,10 +3601,13 @@ module ts {
|
||||
}
|
||||
|
||||
/* If we are widening on a literal, then we may need to the 'node' parameter for reporting purposes */
|
||||
function getWidenedType(type: Type, supressNoImplicitAnyErrors?: boolean): Type {
|
||||
function getWidenedType(type: Type, suppressNoImplicitAnyErrors?: boolean): Type {
|
||||
if (type.flags & (TypeFlags.Undefined | TypeFlags.Null)) {
|
||||
return anyType;
|
||||
}
|
||||
if (type.flags & TypeFlags.Union) {
|
||||
return getWidenedTypeOfUnion(type);
|
||||
}
|
||||
if (isTypeOfObjectLiteral(type)) {
|
||||
return getWidenedTypeOfObjectLiteral(type);
|
||||
}
|
||||
@ -3451,6 +3616,10 @@ module ts {
|
||||
}
|
||||
return type;
|
||||
|
||||
function getWidenedTypeOfUnion(type: Type): Type {
|
||||
return getUnionType(map((<UnionType>type).types, t => getWidenedType(t, suppressNoImplicitAnyErrors)));
|
||||
}
|
||||
|
||||
function getWidenedTypeOfObjectLiteral(type: Type): Type {
|
||||
var properties = getPropertiesOfType(type);
|
||||
if (properties.length) {
|
||||
@ -3461,8 +3630,7 @@ module ts {
|
||||
var widenedType = getWidenedType(propType);
|
||||
if (propType !== widenedType) {
|
||||
propTypeWasWidened = true;
|
||||
|
||||
if (!supressNoImplicitAnyErrors && program.getCompilerOptions().noImplicitAny && getInnermostTypeOfNestedArrayTypes(widenedType) === anyType) {
|
||||
if (!suppressNoImplicitAnyErrors && compilerOptions.noImplicitAny && getInnermostTypeOfNestedArrayTypes(widenedType) === anyType) {
|
||||
error(p.valueDeclaration, Diagnostics.Object_literal_s_property_0_implicitly_has_an_1_type, p.name, typeToString(widenedType));
|
||||
}
|
||||
}
|
||||
@ -3492,10 +3660,8 @@ module ts {
|
||||
|
||||
function getWidenedTypeOfArrayLiteral(type: Type): Type {
|
||||
var elementType = (<TypeReference>type).typeArguments[0];
|
||||
var widenedType = getWidenedType(elementType, supressNoImplicitAnyErrors);
|
||||
|
||||
var widenedType = getWidenedType(elementType, suppressNoImplicitAnyErrors);
|
||||
type = elementType !== widenedType ? createArrayType(widenedType) : type;
|
||||
|
||||
return type;
|
||||
}
|
||||
}
|
||||
@ -3646,9 +3812,19 @@ module ts {
|
||||
function getInferredType(context: InferenceContext, index: number): Type {
|
||||
var result = context.inferredTypes[index];
|
||||
if (!result) {
|
||||
var commonType = getWidenedType(getBestCommonType(context.inferences[index]));
|
||||
var inferences = context.inferences[index];
|
||||
if (inferences.length) {
|
||||
// Find type that is supertype of all others
|
||||
var supertype = getCommonSupertype(inferences);
|
||||
// Infer widened supertype, or the undefined type for no common supertype
|
||||
var inferredType = supertype ? getWidenedType(supertype) : undefinedType;
|
||||
}
|
||||
else {
|
||||
// Infer the empty object type when no inferences were made
|
||||
inferredType = emptyObjectType;
|
||||
}
|
||||
var constraint = getConstraintOfTypeParameter(context.typeParameters[index]);
|
||||
var result = constraint && !isTypeAssignableTo(commonType, constraint) ? constraint : commonType;
|
||||
var result = constraint && !isTypeAssignableTo(inferredType, constraint) ? constraint : inferredType;
|
||||
context.inferredTypes[index] = result;
|
||||
}
|
||||
return result;
|
||||
@ -4083,10 +4259,7 @@ module ts {
|
||||
return createTupleType(elementTypes);
|
||||
}
|
||||
var contextualElementType = contextualType && !isInferentialContext(contextualMapper) ? getIndexTypeOfType(contextualType, IndexKind.Number) : undefined;
|
||||
var elementType = getBestCommonType(uniqueElements(elementTypes), contextualElementType, true);
|
||||
if (!elementType) {
|
||||
elementType = elements.length ? emptyObjectType : undefinedType;
|
||||
}
|
||||
var elementType = elements.length || contextualElementType ? getBestCommonType(deduplicate(elementTypes), contextualElementType) : undefinedType;
|
||||
return createArrayType(elementType);
|
||||
}
|
||||
|
||||
@ -4380,7 +4553,9 @@ module ts {
|
||||
}
|
||||
}
|
||||
}
|
||||
return getInferredTypes(context);
|
||||
var inferredTypes = getInferredTypes(context);
|
||||
// Inference has failed if the undefined type is in list of inferences
|
||||
return contains(inferredTypes, undefinedType) ? undefined : inferredTypes;
|
||||
}
|
||||
|
||||
function checkTypeArguments(signature: Signature, typeArguments: TypeNode[]): Type[] {
|
||||
@ -4405,7 +4580,6 @@ module ts {
|
||||
if (arg.kind === SyntaxKind.OmittedExpression) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var paramType = getTypeAtPosition(signature, i);
|
||||
// String literals get string literal types unless we're reporting errors
|
||||
var argType = arg.kind === SyntaxKind.StringLiteral && !reportErrors ?
|
||||
@ -4441,26 +4615,30 @@ module ts {
|
||||
}
|
||||
}
|
||||
var relation = candidates.length === 1 ? assignableRelation : subtypeRelation;
|
||||
var lastCandidate: Signature;
|
||||
while (true) {
|
||||
for (var i = 0; i < candidates.length; i++) {
|
||||
if (!signatureHasCorrectArity(node, candidates[i])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
while (true) {
|
||||
var candidateWithCorrectArity = candidates[i];
|
||||
if (candidateWithCorrectArity.typeParameters) {
|
||||
var candidate = candidates[i];
|
||||
if (candidate.typeParameters) {
|
||||
var typeArguments = node.typeArguments ?
|
||||
checkTypeArguments(candidateWithCorrectArity, node.typeArguments) :
|
||||
inferTypeArguments(candidateWithCorrectArity, args, excludeArgument);
|
||||
candidateWithCorrectArity = getSignatureInstantiation(candidateWithCorrectArity, typeArguments);
|
||||
checkTypeArguments(candidate, node.typeArguments) :
|
||||
inferTypeArguments(candidate, args, excludeArgument);
|
||||
if (!typeArguments) {
|
||||
break;
|
||||
}
|
||||
candidate = getSignatureInstantiation(candidate, typeArguments);
|
||||
}
|
||||
if (!checkApplicableSignature(node, candidateWithCorrectArity, relation, excludeArgument, /*reportErrors*/ false)) {
|
||||
lastCandidate = candidate;
|
||||
if (!checkApplicableSignature(node, candidate, relation, excludeArgument, /*reportErrors*/ false)) {
|
||||
break;
|
||||
}
|
||||
var index = excludeArgument ? indexOf(excludeArgument, true) : -1;
|
||||
if (index < 0) {
|
||||
return candidateWithCorrectArity;
|
||||
return candidate;
|
||||
}
|
||||
excludeArgument[index] = false;
|
||||
}
|
||||
@ -4475,8 +4653,8 @@ module ts {
|
||||
// no arguments excluded from assignability checks.
|
||||
// If candidate is undefined, it means that no candidates had a suitable arity. In that case,
|
||||
// skip the checkApplicableSignature check.
|
||||
if (candidateWithCorrectArity) {
|
||||
checkApplicableSignature(node, candidateWithCorrectArity, relation, /*excludeArgument*/ undefined, /*reportErrors*/ true);
|
||||
if (lastCandidate) {
|
||||
checkApplicableSignature(node, lastCandidate, relation, /*excludeArgument*/ undefined, /*reportErrors*/ true);
|
||||
}
|
||||
else {
|
||||
error(node, Diagnostics.Supplied_parameters_do_not_match_any_signature_of_call_target);
|
||||
@ -4563,7 +4741,9 @@ module ts {
|
||||
// but is a subtype of the Function interface, the call is an untyped function call. In an
|
||||
// untyped function call no TypeArgs are permitted, Args can be any argument list, no contextual
|
||||
// types are provided for the argument expressions, and the result is always of type Any.
|
||||
if ((funcType === anyType) || (!callSignatures.length && !constructSignatures.length && isTypeAssignableTo(funcType, globalFunctionType))) {
|
||||
// We exclude union types because we may have a union of function types that happen to have
|
||||
// no common signatures.
|
||||
if (funcType === anyType || (!callSignatures.length && !constructSignatures.length && !(funcType.flags & TypeFlags.Union) && isTypeAssignableTo(funcType, globalFunctionType))) {
|
||||
if (node.typeArguments) {
|
||||
error(node, Diagnostics.Untyped_function_calls_may_not_accept_type_arguments);
|
||||
}
|
||||
@ -4723,7 +4903,7 @@ module ts {
|
||||
|
||||
// Try to return the best common type if we have any return expressions.
|
||||
if (types.length > 0) {
|
||||
var commonType = getBestCommonType(types, /*contextualType:*/ undefined, /*candidatesOnly:*/ true);
|
||||
var commonType = getCommonSupertype(types);
|
||||
if (!commonType) {
|
||||
error(func, Diagnostics.No_best_common_type_exists_among_return_expressions);
|
||||
|
||||
@ -5118,16 +5298,7 @@ module ts {
|
||||
var type1 = checkExpression(node.whenTrue, contextualMapper);
|
||||
var type2 = checkExpression(node.whenFalse, contextualMapper);
|
||||
var contextualType = isInferentialContext(contextualMapper) ? undefined : getContextualType(node);
|
||||
var resultType = getBestCommonType([type1, type2], contextualType, true);
|
||||
if (!resultType) {
|
||||
if (contextualType) {
|
||||
error(node, Diagnostics.No_best_common_type_exists_between_0_1_and_2, typeToString(contextualType), typeToString(type1), typeToString(type2));
|
||||
}
|
||||
else {
|
||||
error(node, Diagnostics.No_best_common_type_exists_between_0_and_1, typeToString(type1), typeToString(type2));
|
||||
}
|
||||
resultType = emptyObjectType;
|
||||
}
|
||||
var resultType = getBestCommonType([type1, type2], contextualType);
|
||||
return resultType;
|
||||
}
|
||||
|
||||
@ -5520,6 +5691,10 @@ module ts {
|
||||
forEach(node.elementTypes, checkSourceElement);
|
||||
}
|
||||
|
||||
function checkUnionType(node: UnionTypeNode) {
|
||||
forEach(node.types, checkSourceElement);
|
||||
}
|
||||
|
||||
function isPrivateWithinAmbient(node: Node): boolean {
|
||||
return (node.flags & NodeFlags.Private) && isInAmbientContext(node);
|
||||
}
|
||||
@ -6782,6 +6957,8 @@ module ts {
|
||||
return checkArrayType(<ArrayTypeNode>node);
|
||||
case SyntaxKind.TupleType:
|
||||
return checkTupleType(<TupleTypeNode>node);
|
||||
case SyntaxKind.TupleType:
|
||||
return checkUnionType(<UnionTypeNode>node);
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
return checkFunctionDeclaration(<FunctionDeclaration>node);
|
||||
case SyntaxKind.Block:
|
||||
|
||||
@ -82,7 +82,7 @@ module ts {
|
||||
return array1.concat(array2);
|
||||
}
|
||||
|
||||
export function uniqueElements<T>(array: T[]): T[] {
|
||||
export function deduplicate<T>(array: T[]): T[] {
|
||||
if (array) {
|
||||
var result: T[] = [];
|
||||
for (var i = 0, len = array.length; i < len; i++) {
|
||||
|
||||
@ -179,8 +179,6 @@ module ts {
|
||||
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." },
|
||||
Invalid_left_hand_side_of_assignment_expression: { code: 2364, category: DiagnosticCategory.Error, key: "Invalid left-hand side of assignment expression." },
|
||||
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}'." },
|
||||
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}'." },
|
||||
No_best_common_type_exists_between_0_and_1: { code: 2367, category: DiagnosticCategory.Error, key: "No best common type exists between '{0}' and '{1}'." },
|
||||
Type_parameter_name_cannot_be_0: { code: 2368, category: DiagnosticCategory.Error, key: "Type parameter name cannot be '{0}'" },
|
||||
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." },
|
||||
A_rest_parameter_must_be_of_an_array_type: { code: 2370, category: DiagnosticCategory.Error, key: "A rest parameter must be of an array type." },
|
||||
|
||||
@ -708,14 +708,6 @@
|
||||
"category": "Error",
|
||||
"code": 2365
|
||||
},
|
||||
"No best common type exists between '{0}', '{1}', and '{2}'.": {
|
||||
"category": "Error",
|
||||
"code": 2366
|
||||
},
|
||||
"No best common type exists between '{0}' and '{1}'.": {
|
||||
"category": "Error",
|
||||
"code": 2367
|
||||
},
|
||||
"Type parameter name cannot be '{0}'": {
|
||||
"category": "Error",
|
||||
"code": 2368
|
||||
|
||||
@ -232,6 +232,8 @@ module ts {
|
||||
return child((<ArrayTypeNode>node).elementType);
|
||||
case SyntaxKind.TupleType:
|
||||
return children((<TupleTypeNode>node).elementTypes);
|
||||
case SyntaxKind.UnionType:
|
||||
return children((<UnionTypeNode>node).types);
|
||||
case SyntaxKind.ArrayLiteral:
|
||||
return children((<ArrayLiteral>node).elements);
|
||||
case SyntaxKind.ObjectLiteral:
|
||||
@ -1728,9 +1730,9 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function parseType(): TypeNode {
|
||||
function parseNonUnionType(): TypeNode {
|
||||
var type = parseNonArrayType();
|
||||
while (type && !scanner.hasPrecedingLineBreak() && parseOptional(SyntaxKind.OpenBracketToken)) {
|
||||
while (!scanner.hasPrecedingLineBreak() && parseOptional(SyntaxKind.OpenBracketToken)) {
|
||||
parseExpected(SyntaxKind.CloseBracketToken);
|
||||
var node = <ArrayTypeNode>createNode(SyntaxKind.ArrayType, type.pos);
|
||||
node.elementType = type;
|
||||
@ -1739,6 +1741,22 @@ module ts {
|
||||
return type;
|
||||
}
|
||||
|
||||
function parseType(): TypeNode {
|
||||
var type = parseNonUnionType();
|
||||
if (token === SyntaxKind.BarToken) {
|
||||
var types = <NodeArray<TypeNode>>[type];
|
||||
types.pos = type.pos;
|
||||
while (parseOptional(SyntaxKind.BarToken)) {
|
||||
types.push(parseNonUnionType());
|
||||
}
|
||||
types.end = getNodeEnd();
|
||||
var node = <UnionTypeNode>createNode(SyntaxKind.UnionType, type.pos);
|
||||
node.types = types;
|
||||
type = finishNode(node);
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
function parseTypeAnnotation(): TypeNode {
|
||||
return parseOptional(SyntaxKind.ColonToken) ? parseType() : undefined;
|
||||
}
|
||||
|
||||
@ -154,6 +154,7 @@ module ts {
|
||||
TypeLiteral,
|
||||
ArrayType,
|
||||
TupleType,
|
||||
UnionType,
|
||||
// Expression
|
||||
ArrayLiteral,
|
||||
ObjectLiteral,
|
||||
@ -224,7 +225,7 @@ module ts {
|
||||
FirstFutureReservedWord = ImplementsKeyword,
|
||||
LastFutureReservedWord = YieldKeyword,
|
||||
FirstTypeNode = TypeReference,
|
||||
LastTypeNode = TupleType,
|
||||
LastTypeNode = UnionType,
|
||||
FirstPunctuation = OpenBraceToken,
|
||||
LastPunctuation = CaretEqualsToken,
|
||||
FirstToken = EndOfFileToken,
|
||||
@ -337,6 +338,10 @@ module ts {
|
||||
elementTypes: NodeArray<TypeNode>;
|
||||
}
|
||||
|
||||
export interface UnionTypeNode extends TypeNode {
|
||||
types: NodeArray<TypeNode>;
|
||||
}
|
||||
|
||||
export interface StringLiteralTypeNode extends TypeNode {
|
||||
text: string;
|
||||
}
|
||||
@ -728,19 +733,20 @@ module ts {
|
||||
ConstructSignature = 0x00010000, // Construct signature
|
||||
IndexSignature = 0x00020000, // Index signature
|
||||
TypeParameter = 0x00040000, // Type parameter
|
||||
UnionProperty = 0x00080000, // Property in union type
|
||||
|
||||
// Export markers (see comment in declareModuleMember in binder)
|
||||
ExportValue = 0x00080000, // Exported value marker
|
||||
ExportType = 0x00100000, // Exported type marker
|
||||
ExportNamespace = 0x00200000, // Exported namespace marker
|
||||
ExportValue = 0x00100000, // Exported value marker
|
||||
ExportType = 0x00200000, // Exported type marker
|
||||
ExportNamespace = 0x00400000, // Exported namespace marker
|
||||
|
||||
Import = 0x00400000, // Import
|
||||
Instantiated = 0x00800000, // Instantiated symbol
|
||||
Merged = 0x01000000, // Merged symbol (created during program binding)
|
||||
Transient = 0x02000000, // Transient symbol (created during type check)
|
||||
Prototype = 0x04000000, // Symbol for the prototype property (without source code representation)
|
||||
Import = 0x00800000, // Import
|
||||
Instantiated = 0x01000000, // Instantiated symbol
|
||||
Merged = 0x02000000, // Merged symbol (created during program binding)
|
||||
Transient = 0x04000000, // Transient symbol (created during type check)
|
||||
Prototype = 0x08000000, // Prototype property (no source representation)
|
||||
|
||||
Value = Variable | Property | EnumMember | Function | Class | Enum | ValueModule | Method | GetAccessor | SetAccessor,
|
||||
Value = Variable | Property | EnumMember | Function | Class | Enum | ValueModule | Method | GetAccessor | SetAccessor | UnionProperty,
|
||||
Type = Class | Interface | Enum | TypeLiteral | ObjectLiteral | TypeParameter,
|
||||
Namespace = ValueModule | NamespaceModule,
|
||||
Module = ValueModule | NamespaceModule,
|
||||
@ -798,6 +804,7 @@ module ts {
|
||||
mapper?: TypeMapper; // Type mapper for instantiation alias
|
||||
referenced?: boolean; // True if alias symbol has been referenced as a value
|
||||
exportAssignSymbol?: Symbol; // Symbol exported from external module
|
||||
unionType?: UnionType; // Containing union type for union property
|
||||
}
|
||||
|
||||
export interface TransientSymbol extends Symbol, SymbolLinks { }
|
||||
@ -845,13 +852,14 @@ module ts {
|
||||
Interface = 0x00000800, // Interface
|
||||
Reference = 0x00001000, // Generic type reference
|
||||
Tuple = 0x00002000, // Tuple
|
||||
Anonymous = 0x00004000, // Anonymous
|
||||
FromSignature = 0x00008000, // Created for signature assignment check
|
||||
Union = 0x00004000, // Union
|
||||
Anonymous = 0x00008000, // Anonymous
|
||||
FromSignature = 0x00010000, // Created for signature assignment check
|
||||
|
||||
Intrinsic = Any | String | Number | Boolean | Void | Undefined | Null,
|
||||
StringLike = String | StringLiteral,
|
||||
NumberLike = Number | Enum,
|
||||
ObjectType = Class | Interface | Reference | Tuple | Anonymous
|
||||
ObjectType = Class | Interface | Reference | Tuple | Union | Anonymous
|
||||
}
|
||||
|
||||
// Properties common to all types
|
||||
@ -909,6 +917,10 @@ module ts {
|
||||
baseArrayType: TypeReference; // Array<T> where T is best common type of element types
|
||||
}
|
||||
|
||||
export interface UnionType extends ObjectType {
|
||||
types: Type[]; // Constituent types
|
||||
}
|
||||
|
||||
// Resolved object type
|
||||
export interface ResolvedObjectType extends ObjectType {
|
||||
members: SymbolTable; // Properties by name
|
||||
@ -941,6 +953,7 @@ module ts {
|
||||
hasStringLiterals: boolean; // True if specialized
|
||||
target?: Signature; // Instantiation target
|
||||
mapper?: TypeMapper; // Instantiation mapper
|
||||
unionSignatures?: Signature[]; // Underlying signatures of a union signature
|
||||
erasedSignatureCache?: Signature; // Erased version of signature (deferred)
|
||||
isolatedSignatureType?: ObjectType; // A manufactured type that just contains the signature for purposes of signature comparison
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user