Introduce ObjectFlags in object types

This commit is contained in:
Anders Hejlsberg 2016-10-20 15:28:32 -07:00
parent df2f32bf05
commit 10c6ab6703
4 changed files with 117 additions and 102 deletions

View File

@ -538,6 +538,10 @@ namespace ts {
return nodeLinks[nodeId] || (nodeLinks[nodeId] = { flags: 0 });
}
function getObjectFlags(type: Type): ObjectFlags {
return type.flags & TypeFlags.ObjectType ? (<ObjectType>type).objectFlags : 0;
}
function isGlobalSourceFile(node: Node) {
return node.kind === SyntaxKind.SourceFile && !isExternalOrCommonJsModule(<SourceFile>node);
}
@ -1589,8 +1593,9 @@ namespace ts {
return type;
}
function createObjectType(kind: TypeFlags, symbol?: Symbol): ObjectType {
const type = <ObjectType>createType(kind);
function createObjectType(objectFlags: ObjectFlags, symbol?: Symbol): ObjectType {
const type = <ObjectType>createType(TypeFlags.ObjectType);
type.objectFlags = objectFlags;
type.symbol = symbol;
return type;
}
@ -1631,7 +1636,7 @@ namespace ts {
}
function createAnonymousType(symbol: Symbol, members: SymbolTable, callSignatures: Signature[], constructSignatures: Signature[], stringIndexInfo: IndexInfo, numberIndexInfo: IndexInfo): ResolvedType {
return setStructuredTypeMembers(createObjectType(TypeFlags.Anonymous, symbol),
return setStructuredTypeMembers(createObjectType(ObjectFlags.Anonymous, symbol),
members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo);
}
@ -2182,7 +2187,7 @@ namespace ts {
}
writer.writeKeyword("this");
}
else if (type.flags & TypeFlags.Reference) {
else if (getObjectFlags(type) & ObjectFlags.Reference) {
writeTypeReference(<TypeReference>type, nextFlags);
}
else if (type.flags & TypeFlags.EnumLiteral) {
@ -2190,11 +2195,11 @@ namespace ts {
writePunctuation(writer, SyntaxKind.DotToken);
appendSymbolNameOnly(type.symbol, writer);
}
else if (type.flags & (TypeFlags.Class | TypeFlags.Interface | TypeFlags.Enum | TypeFlags.TypeParameter)) {
else if (getObjectFlags(type) & (ObjectFlags.Class | ObjectFlags.Interface) || type.flags & (TypeFlags.Enum | TypeFlags.TypeParameter)) {
// The specified symbol flags need to be reinterpreted as type flags
buildSymbolDisplay(type.symbol, writer, enclosingDeclaration, SymbolFlags.Type, SymbolFormatFlags.None, nextFlags);
}
else if (!(flags & TypeFormatFlags.InTypeAlias) && ((type.flags & TypeFlags.Anonymous && !(<AnonymousType>type).target) || type.flags & TypeFlags.UnionOrIntersection) && type.aliasSymbol &&
else if (!(flags & TypeFormatFlags.InTypeAlias) && ((getObjectFlags(type) & ObjectFlags.Anonymous && !(<AnonymousType>type).target) || type.flags & TypeFlags.UnionOrIntersection) && type.aliasSymbol &&
isSymbolAccessible(type.aliasSymbol, enclosingDeclaration, SymbolFlags.Type, /*shouldComputeAliasesToMakeVisible*/ false).accessibility === SymbolAccessibility.Accessible) {
// We emit inferred type as type-alias at the current localtion if all the following is true
// the input type is has alias symbol that is accessible
@ -2208,7 +2213,7 @@ namespace ts {
else if (type.flags & TypeFlags.UnionOrIntersection) {
writeUnionOrIntersectionType(<UnionOrIntersectionType>type, nextFlags);
}
else if (type.flags & TypeFlags.Anonymous) {
else if (getObjectFlags(type) & ObjectFlags.Anonymous) {
writeAnonymousType(<ObjectType>type, nextFlags);
}
else if (type.flags & TypeFlags.StringOrNumberLiteral) {
@ -2264,7 +2269,7 @@ namespace ts {
writePunctuation(writer, SyntaxKind.OpenBracketToken);
writePunctuation(writer, SyntaxKind.CloseBracketToken);
}
else if (type.target.flags & TypeFlags.Tuple) {
else if (type.target.objectFlags & ObjectFlags.Tuple) {
writePunctuation(writer, SyntaxKind.OpenBracketToken);
writeTypeList(type.typeArguments.slice(0, getTypeReferenceArity(type)), SyntaxKind.CommaToken);
writePunctuation(writer, SyntaxKind.CloseBracketToken);
@ -2866,7 +2871,6 @@ namespace ts {
return getSymbolLinks(<Symbol>target).declaredType;
}
if (propertyName === TypeSystemPropertyName.ResolvedBaseConstructorType) {
Debug.assert(!!((<Type>target).flags & TypeFlags.Class));
return (<InterfaceType>target).resolvedBaseConstructorType;
}
if (propertyName === TypeSystemPropertyName.ResolvedReturnType) {
@ -3456,7 +3460,7 @@ namespace ts {
links.type = anyType;
}
else {
const type = createObjectType(TypeFlags.Anonymous, symbol);
const type = createObjectType(ObjectFlags.Anonymous, symbol);
links.type = strictNullChecks && symbol.flags & SymbolFlags.Optional ?
includeFalsyTypes(type, TypeFlags.Undefined) : type;
}
@ -3520,7 +3524,7 @@ namespace ts {
}
function getTargetType(type: Type): Type {
return type.flags & TypeFlags.Reference ? (<TypeReference>type).target : type;
return getObjectFlags(type) & ObjectFlags.Reference ? (<TypeReference>type).target : type;
}
function hasBaseType(type: InterfaceType, checkBase: InterfaceType) {
@ -3653,7 +3657,7 @@ namespace ts {
function getBaseTypes(type: InterfaceType): ObjectType[] {
if (!type.resolvedBaseTypes) {
if (type.flags & TypeFlags.Tuple) {
if (type.objectFlags & ObjectFlags.Tuple) {
type.resolvedBaseTypes = [createArrayType(getUnionType(type.typeParameters))];
}
else if (type.symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
@ -3701,7 +3705,7 @@ namespace ts {
if (baseType === unknownType) {
return;
}
if (!(getTargetType(baseType).flags & (TypeFlags.Class | TypeFlags.Interface))) {
if (!(getObjectFlags(getTargetType(baseType)) & (ObjectFlags.Class | ObjectFlags.Interface))) {
error(baseTypeNode.expression, Diagnostics.Base_constructor_return_type_0_is_not_a_class_or_interface_type, typeToString(baseType));
return;
}
@ -3737,7 +3741,7 @@ namespace ts {
for (const node of getInterfaceBaseTypeNodes(<InterfaceDeclaration>declaration)) {
const baseType = getTypeFromTypeNode(node);
if (baseType !== unknownType) {
if (getTargetType(baseType).flags & (TypeFlags.Class | TypeFlags.Interface)) {
if (getObjectFlags(getTargetType(baseType)) & (ObjectFlags.Class | ObjectFlags.Interface)) {
if (type !== baseType && !hasBaseType(<InterfaceType>baseType, type)) {
if (type.resolvedBaseTypes === emptyArray) {
type.resolvedBaseTypes = [<ObjectType>baseType];
@ -3787,7 +3791,7 @@ namespace ts {
function getDeclaredTypeOfClassOrInterface(symbol: Symbol): InterfaceType {
const links = getSymbolLinks(symbol);
if (!links.declaredType) {
const kind = symbol.flags & SymbolFlags.Class ? TypeFlags.Class : TypeFlags.Interface;
const kind = symbol.flags & SymbolFlags.Class ? ObjectFlags.Class : ObjectFlags.Interface;
const type = links.declaredType = <InterfaceType>createObjectType(kind, symbol);
const outerTypeParameters = getOuterTypeParametersOfClassOrInterface(symbol);
const localTypeParameters = getLocalTypeParametersOfClassOrInterfaceOrTypeAlias(symbol);
@ -3796,8 +3800,8 @@ namespace ts {
// property types inferred from initializers and method return types inferred from return statements are very hard
// to exhaustively analyze). We give interfaces a "this" type if we can't definitely determine that they are free of
// "this" references.
if (outerTypeParameters || localTypeParameters || kind === TypeFlags.Class || !isIndependentInterface(symbol)) {
type.flags |= TypeFlags.Reference;
if (outerTypeParameters || localTypeParameters || kind === ObjectFlags.Class || !isIndependentInterface(symbol)) {
type.objectFlags |= ObjectFlags.Reference;
type.typeParameters = concatenate(outerTypeParameters, localTypeParameters);
type.outerTypeParameters = outerTypeParameters;
type.localTypeParameters = localTypeParameters;
@ -4094,7 +4098,7 @@ namespace ts {
}
function getTypeWithThisArgument(type: Type, thisArgument?: Type) {
if (type.flags & TypeFlags.Reference) {
if (getObjectFlags(type) & ObjectFlags.Reference) {
return createTypeReference((<TypeReference>type).target,
concatenate((<TypeReference>type).typeArguments, [thisArgument || (<TypeReference>type).target.thisType]));
}
@ -4365,14 +4369,16 @@ namespace ts {
function resolveStructuredTypeMembers(type: StructuredType): ResolvedType {
if (!(<ResolvedType>type).members) {
if (type.flags & TypeFlags.Reference) {
resolveTypeReferenceMembers(<TypeReference>type);
}
else if (type.flags & (TypeFlags.Class | TypeFlags.Interface)) {
resolveClassOrInterfaceMembers(<InterfaceType>type);
}
else if (type.flags & TypeFlags.Anonymous) {
resolveAnonymousTypeMembers(<AnonymousType>type);
if (type.flags & TypeFlags.ObjectType) {
if ((<ObjectType>type).objectFlags & ObjectFlags.Reference) {
resolveTypeReferenceMembers(<TypeReference>type);
}
else if ((<ObjectType>type).objectFlags & (ObjectFlags.Class | ObjectFlags.Interface)) {
resolveClassOrInterfaceMembers(<InterfaceType>type);
}
else if ((<ObjectType>type).objectFlags & ObjectFlags.Anonymous) {
resolveAnonymousTypeMembers(<AnonymousType>type);
}
}
else if (type.flags & TypeFlags.Union) {
resolveUnionTypeMembers(<UnionType>type);
@ -4927,7 +4933,7 @@ namespace ts {
function getRestTypeOfSignature(signature: Signature): Type {
if (signature.hasRestParameter) {
const type = getTypeOfSymbol(lastOrUndefined(signature.parameters));
if (type.flags & TypeFlags.Reference && (<TypeReference>type).target === globalArrayType) {
if (getObjectFlags(type) & ObjectFlags.Reference && (<TypeReference>type).target === globalArrayType) {
return (<TypeReference>type).typeArguments[0];
}
}
@ -4953,7 +4959,7 @@ namespace ts {
// will result in a different declaration kind.
if (!signature.isolatedSignatureType) {
const isConstructor = signature.declaration.kind === SyntaxKind.Constructor || signature.declaration.kind === SyntaxKind.ConstructSignature;
const type = <ResolvedType>createObjectType(TypeFlags.Anonymous);
const type = <ResolvedType>createObjectType(ObjectFlags.Anonymous);
type.members = emptySymbols;
type.properties = emptyArray;
type.callSignatures = !isConstructor ? [signature] : emptyArray;
@ -5081,9 +5087,8 @@ namespace ts {
const id = getTypeListId(typeArguments);
let type = target.instantiations[id];
if (!type) {
const propagatedFlags = typeArguments ? getPropagatingFlagsOfTypes(typeArguments, /*excludeKinds*/ 0) : 0;
const flags = TypeFlags.Reference | propagatedFlags;
type = target.instantiations[id] = <TypeReference>createObjectType(flags, target.symbol);
type = target.instantiations[id] = <TypeReference>createObjectType(ObjectFlags.Reference, target.symbol);
type.flags |= typeArguments ? getPropagatingFlagsOfTypes(typeArguments, /*excludeKinds*/ 0) : 0;
type.target = target;
type.typeArguments = typeArguments;
}
@ -5091,7 +5096,9 @@ namespace ts {
}
function cloneTypeReference(source: TypeReference): TypeReference {
const type = <TypeReference>createObjectType(source.flags, source.symbol);
const type = <TypeReference>createType(source.flags);
type.symbol = source.symbol;
type.objectFlags = source.objectFlags;
type.target = source.target;
type.typeArguments = source.typeArguments;
return type;
@ -5357,7 +5364,7 @@ namespace ts {
property.type = typeParameter;
properties.push(property);
}
const type = <GenericType & InterfaceTypeWithDeclaredMembers>createObjectType(TypeFlags.Tuple | TypeFlags.Reference);
const type = <GenericType & InterfaceTypeWithDeclaredMembers>createObjectType(ObjectFlags.Tuple | ObjectFlags.Reference);
type.typeParameters = typeParameters;
type.outerTypeParameters = undefined;
type.localTypeParameters = typeParameters;
@ -5446,7 +5453,8 @@ namespace ts {
const len = typeSet.length;
const index = len && type.id > typeSet[len - 1].id ? ~len : binarySearchTypes(typeSet, type);
if (index < 0) {
if (!(flags & TypeFlags.Anonymous && type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method) && containsIdenticalType(typeSet, type))) {
if (!(flags & TypeFlags.ObjectType && (<ObjectType>type).objectFlags & ObjectFlags.Anonymous &&
type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method) && containsIdenticalType(typeSet, type))) {
typeSet.splice(~index, 0, type);
}
}
@ -5659,7 +5667,7 @@ namespace ts {
const links = getNodeLinks(node);
if (!links.resolvedType) {
// Deferred resolution of members is handled by resolveObjectTypeMembers
const type = createObjectType(TypeFlags.Anonymous, node.symbol);
const type = createObjectType(ObjectFlags.Anonymous, node.symbol);
type.aliasSymbol = aliasSymbol;
type.aliasTypeArguments = aliasTypeArguments;
links.resolvedType = type;
@ -5989,7 +5997,7 @@ namespace ts {
mapper.instantiations = [];
}
// Mark the anonymous type as instantiated such that our infinite instantiation detection logic can recognize it
const result = <AnonymousType>createObjectType(TypeFlags.Anonymous | TypeFlags.Instantiated, type.symbol);
const result = <AnonymousType>createObjectType(ObjectFlags.Anonymous | ObjectFlags.Instantiated, type.symbol);
result.target = type;
result.mapper = mapper;
result.aliasSymbol = type.aliasSymbol;
@ -6052,20 +6060,22 @@ namespace ts {
if (type.flags & TypeFlags.TypeParameter) {
return mapper(<TypeParameter>type);
}
if (type.flags & TypeFlags.Anonymous) {
// If the anonymous type originates in a declaration of a function, method, class, or
// interface, in an object type literal, or in an object literal expression, we may need
// to instantiate the type because it might reference a type parameter. We skip instantiation
// if none of the type parameters that are in scope in the type's declaration are mapped by
// the given mapper, however we can only do that analysis if the type isn't itself an
// instantiation.
return type.symbol &&
type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral) &&
(type.flags & TypeFlags.Instantiated || isSymbolInScopeOfMappedTypeParameter(type.symbol, mapper)) ?
instantiateAnonymousType(<AnonymousType>type, mapper) : type;
}
if (type.flags & TypeFlags.Reference) {
return createTypeReference((<TypeReference>type).target, instantiateList((<TypeReference>type).typeArguments, mapper, instantiateType));
if (type.flags & TypeFlags.ObjectType) {
if ((<ObjectType>type).objectFlags & ObjectFlags.Anonymous) {
// If the anonymous type originates in a declaration of a function, method, class, or
// interface, in an object type literal, or in an object literal expression, we may need
// to instantiate the type because it might reference a type parameter. We skip instantiation
// if none of the type parameters that are in scope in the type's declaration are mapped by
// the given mapper, however we can only do that analysis if the type isn't itself an
// instantiation.
return type.symbol &&
type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral) &&
((<ObjectType>type).objectFlags & ObjectFlags.Instantiated || isSymbolInScopeOfMappedTypeParameter(type.symbol, mapper)) ?
instantiateAnonymousType(<AnonymousType>type, mapper) : type;
}
if ((<ObjectType>type).objectFlags & ObjectFlags.Reference) {
return createTypeReference((<TypeReference>type).target, instantiateList((<TypeReference>type).typeArguments, mapper, instantiateType));
}
}
if (type.flags & TypeFlags.Union && !(type.flags & TypeFlags.Primitive)) {
return getUnionType(instantiateList((<UnionType>type).types, mapper, instantiateType), /*subtypeReduction*/ false, type.aliasSymbol, mapper.targetTypes);
@ -6140,7 +6150,7 @@ namespace ts {
if (type.flags & TypeFlags.ObjectType) {
const resolved = resolveStructuredTypeMembers(<ObjectType>type);
if (resolved.constructSignatures.length) {
const result = <ResolvedType>createObjectType(TypeFlags.Anonymous, type.symbol);
const result = <ResolvedType>createObjectType(ObjectFlags.Anonymous, type.symbol);
result.members = resolved.members;
result.properties = resolved.properties;
result.callSignatures = emptyArray;
@ -6556,7 +6566,7 @@ namespace ts {
if (isSimpleTypeRelatedTo(source, target, relation, reportErrors ? reportError : undefined)) return Ternary.True;
if (source.flags & TypeFlags.ObjectLiteral && source.flags & TypeFlags.FreshLiteral) {
if (getObjectFlags(source) & ObjectFlags.ObjectLiteral && source.flags & TypeFlags.FreshLiteral) {
if (hasExcessProperties(<FreshObjectLiteralType>source, target, reportErrors)) {
if (reportErrors) {
reportRelationError(headMessage, source, target);
@ -6635,7 +6645,7 @@ namespace ts {
}
}
else {
if (source.flags & TypeFlags.Reference && target.flags & TypeFlags.Reference && (<TypeReference>source).target === (<TypeReference>target).target) {
if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (<TypeReference>source).target === (<TypeReference>target).target) {
// We have type references to same target type, see if relationship holds for all type arguments
if (result = typeArgumentsRelatedTo(<TypeReference>source, <TypeReference>target, reportErrors)) {
return result;
@ -6672,7 +6682,7 @@ namespace ts {
function isIdenticalTo(source: Type, target: Type): Ternary {
let result: Ternary;
if (source.flags & TypeFlags.ObjectType && target.flags & TypeFlags.ObjectType) {
if (source.flags & TypeFlags.Reference && target.flags & TypeFlags.Reference && (<TypeReference>source).target === (<TypeReference>target).target) {
if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (<TypeReference>source).target === (<TypeReference>target).target) {
// We have type references to same target type, see if all type arguments are identical
if (result = typeArgumentsRelatedTo(<TypeReference>source, <TypeReference>target, /*reportErrors*/ false)) {
return result;
@ -6919,7 +6929,7 @@ namespace ts {
}
let result = Ternary.True;
const properties = getPropertiesOfObjectType(target);
const requireOptionalProperties = relation === subtypeRelation && !(source.flags & TypeFlags.ObjectLiteral);
const requireOptionalProperties = relation === subtypeRelation && !(getObjectFlags(source) & ObjectFlags.ObjectLiteral);
for (const targetProp of properties) {
const sourceProp = getPropertyOfType(source, targetProp.name);
@ -7200,7 +7210,7 @@ namespace ts {
// Return true if the given type is the constructor type for an abstract class
function isAbstractConstructorType(type: Type) {
if (type.flags & TypeFlags.Anonymous) {
if (getObjectFlags(type) & ObjectFlags.Anonymous) {
const symbol = type.symbol;
if (symbol && symbol.flags & SymbolFlags.Class) {
const declaration = getClassLikeDeclarationOfSymbol(symbol);
@ -7219,12 +7229,12 @@ namespace ts {
// some level beyond that.
function isDeeplyNestedGeneric(type: Type, stack: Type[], depth: number): boolean {
// We track type references (created by createTypeReference) and instantiated types (created by instantiateType)
if (type.flags & (TypeFlags.Reference | TypeFlags.Instantiated) && depth >= 5) {
if (getObjectFlags(type) & (ObjectFlags.Reference | ObjectFlags.Instantiated) && depth >= 5) {
const symbol = type.symbol;
let count = 0;
for (let i = 0; i < depth; i++) {
const t = stack[i];
if (t.flags & (TypeFlags.Reference | TypeFlags.Instantiated) && t.symbol === symbol) {
if (getObjectFlags(t) & (ObjectFlags.Reference | ObjectFlags.Instantiated) && t.symbol === symbol) {
count++;
if (count >= 5) return true;
}
@ -7427,13 +7437,13 @@ namespace ts {
}
function isArrayType(type: Type): boolean {
return type.flags & TypeFlags.Reference && (<TypeReference>type).target === globalArrayType;
return getObjectFlags(type) & ObjectFlags.Reference && (<TypeReference>type).target === globalArrayType;
}
function isArrayLikeType(type: Type): boolean {
// A type is array-like if it is a reference to the global Array or global ReadonlyArray type,
// or if it is not the undefined or null type and if it is assignable to ReadonlyArray<any>
return type.flags & TypeFlags.Reference && ((<TypeReference>type).target === globalArrayType || (<TypeReference>type).target === globalReadonlyArrayType) ||
return getObjectFlags(type) & ObjectFlags.Reference && ((<TypeReference>type).target === globalArrayType || (<TypeReference>type).target === globalReadonlyArrayType) ||
!(type.flags & TypeFlags.Nullable) && isTypeAssignableTo(type, anyReadonlyArrayType);
}
@ -7474,7 +7484,7 @@ namespace ts {
* Prefer using isTupleLikeType() unless the use of `elementTypes` is required.
*/
function isTupleType(type: Type): boolean {
return !!(type.flags & TypeFlags.Reference && (<TypeReference>type).target.flags & TypeFlags.Tuple);
return !!(getObjectFlags(type) & ObjectFlags.Reference && (<TypeReference>type).target.objectFlags & ObjectFlags.Tuple);
}
function getFalsyFlagsOfTypes(types: Type[]): TypeFlags {
@ -7558,7 +7568,7 @@ namespace ts {
* Leave signatures alone since they are not subject to the check.
*/
function getRegularTypeOfObjectLiteral(type: Type): Type {
if (!(type.flags & TypeFlags.ObjectLiteral && type.flags & TypeFlags.FreshLiteral)) {
if (!(getObjectFlags(type) & ObjectFlags.ObjectLiteral && type.flags & TypeFlags.FreshLiteral)) {
return type;
}
const regularType = (<FreshObjectLiteralType>type).regularType;
@ -7575,6 +7585,7 @@ namespace ts {
resolved.stringIndexInfo,
resolved.numberIndexInfo);
regularNew.flags = resolved.flags & ~TypeFlags.FreshLiteral;
regularNew.objectFlags |= ObjectFlags.ObjectLiteral;
(<FreshObjectLiteralType>type).regularType = regularNew;
return regularNew;
}
@ -7600,7 +7611,7 @@ namespace ts {
if (type.flags & TypeFlags.Nullable) {
return anyType;
}
if (type.flags & TypeFlags.ObjectLiteral) {
if (getObjectFlags(type) & ObjectFlags.ObjectLiteral) {
return getWidenedTypeOfObjectLiteral(type);
}
if (type.flags & TypeFlags.Union) {
@ -7640,7 +7651,7 @@ namespace ts {
}
}
}
if (type.flags & TypeFlags.ObjectLiteral) {
if (getObjectFlags(type) & ObjectFlags.ObjectLiteral) {
for (const p of getPropertiesOfObjectType(type)) {
const t = getTypeOfSymbol(p);
if (t.flags & TypeFlags.ContainsWideningType) {
@ -7743,8 +7754,8 @@ namespace ts {
// results for union and intersection types for performance reasons.
function couldContainTypeParameters(type: Type): boolean {
return !!(type.flags & TypeFlags.TypeParameter ||
type.flags & TypeFlags.Reference && forEach((<TypeReference>type).typeArguments, couldContainTypeParameters) ||
type.flags & TypeFlags.Anonymous && type.symbol && type.symbol.flags & (SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class) ||
getObjectFlags(type) & ObjectFlags.Reference && forEach((<TypeReference>type).typeArguments, couldContainTypeParameters) ||
getObjectFlags(type) & ObjectFlags.Anonymous && type.symbol && type.symbol.flags & (SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class) ||
type.flags & TypeFlags.UnionOrIntersection && couldUnionOrIntersectionContainTypeParameters(<UnionOrIntersectionType>type));
}
@ -7852,7 +7863,7 @@ namespace ts {
}
}
}
else if (source.flags & TypeFlags.Reference && target.flags & TypeFlags.Reference && (<TypeReference>source).target === (<TypeReference>target).target) {
else if (getObjectFlags(source) & ObjectFlags.Reference && getObjectFlags(target) & ObjectFlags.Reference && (<TypeReference>source).target === (<TypeReference>target).target) {
// If source and target are references to the same generic type, infer from type arguments
const sourceTypes = (<TypeReference>source).typeArguments || emptyArray;
const targetTypes = (<TypeReference>target).typeArguments || emptyArray;
@ -8548,7 +8559,7 @@ namespace ts {
// array types are ultimately converted into manifest array types (using getFinalArrayType)
// and never escape the getFlowTypeOfReference function.
function createEvolvingArrayType(elementType: Type): AnonymousType {
const result = <AnonymousType>createObjectType(TypeFlags.Anonymous);
const result = <AnonymousType>createObjectType(ObjectFlags.Anonymous);
result.elementType = elementType;
return result;
}
@ -8566,7 +8577,7 @@ namespace ts {
}
function isEvolvingArrayType(type: Type) {
return !!(type.flags & TypeFlags.Anonymous && (<AnonymousType>type).elementType);
return !!(getObjectFlags(type) & ObjectFlags.Anonymous && (<AnonymousType>type).elementType);
}
function createFinalArrayType(elementType: Type) {
@ -9101,10 +9112,10 @@ namespace ts {
if (!targetType) {
// Target type is type of construct signature
let constructSignatures: Signature[];
if (rightType.flags & TypeFlags.Interface) {
if (getObjectFlags(rightType) & ObjectFlags.Interface) {
constructSignatures = resolveDeclaredMembers(<InterfaceType>rightType).declaredConstructSignatures;
}
else if (rightType.flags & TypeFlags.Anonymous) {
else if (getObjectFlags(rightType) & ObjectFlags.Anonymous) {
constructSignatures = getSignaturesOfType(rightType, SignatureKind.Construct);
}
if (constructSignatures && constructSignatures.length) {
@ -10654,7 +10665,8 @@ namespace ts {
const numberIndexInfo = hasComputedNumberProperty ? getObjectLiteralIndexInfo(node, propertiesArray, IndexKind.Number) : undefined;
const result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo);
const freshObjectLiteralFlag = compilerOptions.suppressExcessPropertyErrors ? 0 : TypeFlags.FreshLiteral;
result.flags |= TypeFlags.ObjectLiteral | TypeFlags.ContainsObjectLiteral | freshObjectLiteralFlag | (typeFlags & TypeFlags.PropagatingFlags);
result.flags |= TypeFlags.ContainsObjectLiteral | freshObjectLiteralFlag | (typeFlags & TypeFlags.PropagatingFlags);
result.objectFlags |= ObjectFlags.ObjectLiteral;
if (patternWithComputedProperties) {
result.isObjectLiteralPatternWithComputedProperties = true;
}
@ -11239,7 +11251,7 @@ namespace ts {
}
// TODO: why is the first part of this check here?
if (!(getTargetType(type).flags & (TypeFlags.Class | TypeFlags.Interface) && hasBaseType(<InterfaceType>type, enclosingClass))) {
if (!(getObjectFlags(getTargetType(type)) & (ObjectFlags.Class | ObjectFlags.Interface) && hasBaseType(<InterfaceType>type, enclosingClass))) {
error(errorNode, Diagnostics.Property_0_is_protected_and_only_accessible_through_an_instance_of_class_1, symbolToString(prop), typeToString(enclosingClass));
return false;
}
@ -13528,7 +13540,7 @@ namespace ts {
}
function isConstEnumObjectType(type: Type): boolean {
return type.flags & (TypeFlags.ObjectType | TypeFlags.Anonymous) && type.symbol && isConstEnumSymbol(type.symbol);
return getObjectFlags(type) & ObjectFlags.Anonymous && type.symbol && isConstEnumSymbol(type.symbol);
}
function isConstEnumSymbol(symbol: Symbol): boolean {
@ -15293,7 +15305,7 @@ namespace ts {
return undefined;
}
if (promise.flags & TypeFlags.Reference) {
if (getObjectFlags(promise) & ObjectFlags.Reference) {
if ((<GenericType>promise).target === tryGetGlobalPromiseType()
|| (<GenericType>promise).target === getGlobalPromiseLikeType()) {
return (<GenericType>promise).typeArguments[0];
@ -16562,7 +16574,7 @@ namespace ts {
if (!typeAsIterable.iterableElementType) {
// As an optimization, if the type is instantiated directly using the globalIterableType (Iterable<number>),
// then just grab its type argument.
if ((type.flags & TypeFlags.Reference) && (<GenericType>type).target === getGlobalIterableType()) {
if ((getObjectFlags(type) & ObjectFlags.Reference) && (<GenericType>type).target === getGlobalIterableType()) {
typeAsIterable.iterableElementType = (<GenericType>type).typeArguments[0];
}
else {
@ -16608,7 +16620,7 @@ namespace ts {
if (!typeAsIterator.iteratorElementType) {
// As an optimization, if the type is instantiated directly using the globalIteratorType (Iterator<number>),
// then just grab its type argument.
if ((type.flags & TypeFlags.Reference) && (<GenericType>type).target === getGlobalIteratorType()) {
if ((getObjectFlags(type) & ObjectFlags.Reference) && (<GenericType>type).target === getGlobalIteratorType()) {
typeAsIterator.iteratorElementType = (<GenericType>type).typeArguments[0];
}
else {
@ -16652,7 +16664,7 @@ namespace ts {
// As an optimization, if the type is instantiated directly using the globalIterableIteratorType (IterableIterator<number>),
// then just grab its type argument.
if ((type.flags & TypeFlags.Reference) && (<GenericType>type).target === getGlobalIterableIteratorType()) {
if ((getObjectFlags(type) & ObjectFlags.Reference) && (<GenericType>type).target === getGlobalIterableIteratorType()) {
return (<GenericType>type).typeArguments[0];
}
@ -16949,7 +16961,7 @@ namespace ts {
checkIndexConstraintForProperty(prop, propType, type, declaredNumberIndexer, numberIndexType, IndexKind.Number);
});
if (type.flags & TypeFlags.Class && isClassLike(type.symbol.valueDeclaration)) {
if (getObjectFlags(type) & ObjectFlags.Class && isClassLike(type.symbol.valueDeclaration)) {
const classDeclaration = <ClassLikeDeclaration>type.symbol.valueDeclaration;
for (const member of classDeclaration.members) {
// Only process instance properties with computed names here.
@ -16968,7 +16980,7 @@ namespace ts {
if (stringIndexType && numberIndexType) {
errorNode = declaredNumberIndexer || declaredStringIndexer;
// condition 'errorNode === undefined' may appear if types does not declare nor string neither number indexer
if (!errorNode && (type.flags & TypeFlags.Interface)) {
if (!errorNode && (getObjectFlags(type) & ObjectFlags.Interface)) {
const someBaseTypeHasBothIndexers = forEach(getBaseTypes(<InterfaceType>type), base => getIndexTypeOfType(base, IndexKind.String) && getIndexTypeOfType(base, IndexKind.Number));
errorNode = someBaseTypeHasBothIndexers ? undefined : type.symbol.declarations[0];
}
@ -17005,7 +17017,7 @@ namespace ts {
else if (indexDeclaration) {
errorNode = indexDeclaration;
}
else if (containingType.flags & TypeFlags.Interface) {
else if (getObjectFlags(containingType) & ObjectFlags.Interface) {
// for interfaces property and indexer might be inherited from different bases
// check if any base class already has both property and indexer.
// check should be performed only if 'type' is the first type that brings property\indexer together
@ -17164,8 +17176,8 @@ namespace ts {
if (produceDiagnostics) {
const t = getTypeFromTypeNode(typeRefNode);
if (t !== unknownType) {
const declaredType = (t.flags & TypeFlags.Reference) ? (<TypeReference>t).target : t;
if (declaredType.flags & (TypeFlags.Class | TypeFlags.Interface)) {
const declaredType = (getObjectFlags(t) & ObjectFlags.Reference) ? (<TypeReference>t).target : t;
if (getObjectFlags(declaredType) & (ObjectFlags.Class | ObjectFlags.Interface)) {
checkTypeAssignableTo(typeWithThis, getTypeWithThisArgument(t, type.thisType), node.name || node, Diagnostics.Class_0_incorrectly_implements_interface_1);
}
else {
@ -19671,7 +19683,7 @@ namespace ts {
const thenPropertySymbol = createSymbol(SymbolFlags.Transient | SymbolFlags.Property, "then");
getSymbolLinks(thenPropertySymbol).type = globalFunctionType;
const thenableType = <ResolvedType>createObjectType(TypeFlags.Anonymous);
const thenableType = <ResolvedType>createObjectType(ObjectFlags.Anonymous);
thenableType.properties = [thenPropertySymbol];
thenableType.members = createSymbolTable(thenableType.properties);
thenableType.callSignatures = [];

View File

@ -2612,24 +2612,17 @@ namespace ts {
Null = 1 << 12,
Never = 1 << 13, // Never type
TypeParameter = 1 << 14, // Type parameter
Class = 1 << 15, // Class
Interface = 1 << 16, // Interface
Reference = 1 << 17, // Generic type reference
Tuple = 1 << 18, // Synthesized generic tuple type
Union = 1 << 19, // Union (T | U)
Intersection = 1 << 20, // Intersection (T & U)
Anonymous = 1 << 21, // Anonymous
Instantiated = 1 << 22, // Instantiated anonymous type
ObjectType = 1 << 15, // Object type
Union = 1 << 16, // Union (T | U)
Intersection = 1 << 17, // Intersection (T & U)
/* @internal */
ObjectLiteral = 1 << 23, // Originates in an object literal
FreshLiteral = 1 << 18, // Fresh literal type
/* @internal */
FreshLiteral = 1 << 24, // Fresh literal type
ContainsWideningType = 1 << 19, // Type is or contains undefined or null widening type
/* @internal */
ContainsWideningType = 1 << 25, // Type is or contains undefined or null widening type
ContainsObjectLiteral = 1 << 20, // Type is or contains object literal type
/* @internal */
ContainsObjectLiteral = 1 << 26, // Type is or contains object literal type
/* @internal */
ContainsAnyFunctionType = 1 << 27, // Type is or contains object literal type
ContainsAnyFunctionType = 1 << 21, // Type is or contains object literal type
/* @internal */
Nullable = Undefined | Null,
@ -2646,7 +2639,6 @@ namespace ts {
NumberLike = Number | NumberLiteral | Enum | EnumLiteral,
BooleanLike = Boolean | BooleanLiteral,
EnumLike = Enum | EnumLiteral,
ObjectType = Class | Interface | Reference | Tuple | Anonymous,
UnionOrIntersection = Union | Intersection,
StructuredType = ObjectType | Union | Intersection,
StructuredOrTypeParameter = StructuredType | TypeParameter,
@ -2663,6 +2655,16 @@ namespace ts {
export type DestructuringPattern = BindingPattern | ObjectLiteralExpression | ArrayLiteralExpression;
export const enum ObjectFlags {
Class = 1 << 0, // Class
Interface = 1 << 1, // Interface
Reference = 1 << 2, // Generic type reference
Tuple = 1 << 3, // Synthesized generic tuple type
Anonymous = 1 << 4, // Anonymous
Instantiated = 1 << 5, // Instantiated anonymous type
ObjectLiteral = 1 << 6, // Originates in an object literal
}
// Properties common to all types
export interface Type {
flags: TypeFlags; // Flags
@ -2699,7 +2701,7 @@ namespace ts {
// Object types (TypeFlags.ObjectType)
export interface ObjectType extends Type {
_objectTypeBrand: any;
objectFlags: ObjectFlags;
isObjectLiteralPatternWithComputedProperties?: boolean;
}

View File

@ -347,6 +347,7 @@ namespace ts {
class TypeObject implements Type {
checker: TypeChecker;
flags: TypeFlags;
objectFlags?: ObjectFlags;
id: number;
symbol: Symbol;
constructor(checker: TypeChecker, flags: TypeFlags) {
@ -381,7 +382,7 @@ namespace ts {
return this.checker.getIndexTypeOfType(this, IndexKind.Number);
}
getBaseTypes(): ObjectType[] {
return this.flags & (TypeFlags.Class | TypeFlags.Interface)
return this.flags & TypeFlags.ObjectType && this.objectFlags & (ObjectFlags.Class | ObjectFlags.Interface)
? this.checker.getBaseTypes(<InterfaceType><Type>this)
: undefined;
}

View File

@ -173,7 +173,7 @@ namespace ts.SymbolDisplay {
displayParts.push(keywordPart(SyntaxKind.NewKeyword));
displayParts.push(spacePart());
}
if (!(type.flags & TypeFlags.Anonymous) && type.symbol) {
if (!(type.flags & TypeFlags.ObjectType && (<ObjectType>type).objectFlags & ObjectFlags.Anonymous) && type.symbol) {
addRange(displayParts, symbolToDisplayParts(typeChecker, type.symbol, enclosingDeclaration, /*meaning*/ undefined, SymbolFormatFlags.WriteTypeParametersOrArguments));
}
addSignatureDisplayParts(signature, allSignatures, TypeFormatFlags.WriteArrowStyleSignature);