Properly distinguish between Type, ObjectType, and StructuredType

This commit is contained in:
Anders Hejlsberg 2016-10-20 11:15:44 -07:00
parent 4fbbbed321
commit df2f32bf05
2 changed files with 36 additions and 33 deletions

View File

@ -323,9 +323,9 @@ namespace ts {
"undefined": undefinedType
});
let jsxElementType: ObjectType;
let jsxElementType: Type;
/** Things we lazy load from the JSX namespace */
const jsxTypes = createMap<ObjectType>();
const jsxTypes = createMap<Type>();
const JsxNames = {
JSX: "JSX",
IntrinsicElements: "IntrinsicElements",
@ -1620,7 +1620,7 @@ namespace ts {
return result || emptyArray;
}
function setObjectTypeMembers(type: ObjectType, members: SymbolTable, callSignatures: Signature[], constructSignatures: Signature[], stringIndexInfo: IndexInfo, numberIndexInfo: IndexInfo): ResolvedType {
function setStructuredTypeMembers(type: StructuredType, members: SymbolTable, callSignatures: Signature[], constructSignatures: Signature[], stringIndexInfo: IndexInfo, numberIndexInfo: IndexInfo): ResolvedType {
(<ResolvedType>type).members = members;
(<ResolvedType>type).properties = getNamedMembers(members);
(<ResolvedType>type).callSignatures = callSignatures;
@ -1631,7 +1631,7 @@ namespace ts {
}
function createAnonymousType(symbol: Symbol, members: SymbolTable, callSignatures: Signature[], constructSignatures: Signature[], stringIndexInfo: IndexInfo, numberIndexInfo: IndexInfo): ResolvedType {
return setObjectTypeMembers(createObjectType(TypeFlags.Anonymous, symbol),
return setStructuredTypeMembers(createObjectType(TypeFlags.Anonymous, symbol),
members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo);
}
@ -3519,7 +3519,7 @@ namespace ts {
return unknownType;
}
function getTargetType(type: ObjectType): Type {
function getTargetType(type: Type): Type {
return type.flags & TypeFlags.Reference ? (<TypeReference>type).target : type;
}
@ -3603,13 +3603,13 @@ namespace ts {
return getClassExtendsHeritageClauseElement(<ClassLikeDeclaration>type.symbol.valueDeclaration);
}
function getConstructorsForTypeArguments(type: ObjectType, typeArgumentNodes: TypeNode[]): Signature[] {
function getConstructorsForTypeArguments(type: Type, typeArgumentNodes: TypeNode[]): Signature[] {
const typeArgCount = typeArgumentNodes ? typeArgumentNodes.length : 0;
return filter(getSignaturesOfType(type, SignatureKind.Construct),
sig => (sig.typeParameters ? sig.typeParameters.length : 0) === typeArgCount);
}
function getInstantiatedConstructorsForTypeArguments(type: ObjectType, typeArgumentNodes: TypeNode[]): Signature[] {
function getInstantiatedConstructorsForTypeArguments(type: Type, typeArgumentNodes: TypeNode[]): Signature[] {
let signatures = getConstructorsForTypeArguments(type, typeArgumentNodes);
if (typeArgumentNodes) {
const typeArguments = map(typeArgumentNodes, getTypeFromTypeNodeNoAlias);
@ -3623,7 +3623,7 @@ namespace ts {
// unknownType if an error occurred during resolution of the extends expression,
// nullType if the extends expression is the null value, or
// an object type with at least one construct signature.
function getBaseConstructorTypeOfClass(type: InterfaceType): ObjectType {
function getBaseConstructorTypeOfClass(type: InterfaceType): Type {
if (!type.resolvedBaseConstructorType) {
const baseTypeNode = getBaseTypeNodeOfClass(type);
if (!baseTypeNode) {
@ -3636,7 +3636,7 @@ namespace ts {
if (baseConstructorType.flags & TypeFlags.ObjectType) {
// Resolving the members of a class requires us to resolve the base class of that class.
// We force resolution here such that we catch circularities now.
resolveStructuredTypeMembers(baseConstructorType);
resolveStructuredTypeMembers(<ObjectType>baseConstructorType);
}
if (!popTypeResolution()) {
error(type.symbol.valueDeclaration, Diagnostics._0_is_referenced_directly_or_indirectly_in_its_own_base_expression, symbolToString(type.symbol));
@ -3673,7 +3673,7 @@ namespace ts {
function resolveBaseTypesOfClass(type: InterfaceType): void {
type.resolvedBaseTypes = type.resolvedBaseTypes || emptyArray;
const baseConstructorType = getBaseConstructorTypeOfClass(type);
const baseConstructorType = <ObjectType>getBaseConstructorTypeOfClass(type);
if (!(baseConstructorType.flags & TypeFlags.ObjectType)) {
return;
}
@ -3711,10 +3711,10 @@ namespace ts {
return;
}
if (type.resolvedBaseTypes === emptyArray) {
type.resolvedBaseTypes = [baseType];
type.resolvedBaseTypes = [<ObjectType>baseType];
}
else {
type.resolvedBaseTypes.push(baseType);
type.resolvedBaseTypes.push(<ObjectType>baseType);
}
}
@ -3740,10 +3740,10 @@ namespace ts {
if (getTargetType(baseType).flags & (TypeFlags.Class | TypeFlags.Interface)) {
if (type !== baseType && !hasBaseType(<InterfaceType>baseType, type)) {
if (type.resolvedBaseTypes === emptyArray) {
type.resolvedBaseTypes = [baseType];
type.resolvedBaseTypes = [<ObjectType>baseType];
}
else {
type.resolvedBaseTypes.push(baseType);
type.resolvedBaseTypes.push(<ObjectType>baseType);
}
}
else {
@ -4093,7 +4093,7 @@ namespace ts {
return <InterfaceTypeWithDeclaredMembers>type;
}
function getTypeWithThisArgument(type: ObjectType, thisArgument?: Type) {
function getTypeWithThisArgument(type: Type, thisArgument?: Type) {
if (type.flags & TypeFlags.Reference) {
return createTypeReference((<TypeReference>type).target,
concatenate((<TypeReference>type).typeArguments, [thisArgument || (<TypeReference>type).target.thisType]));
@ -4131,7 +4131,7 @@ namespace ts {
}
const thisArgument = lastOrUndefined(typeArguments);
for (const baseType of baseTypes) {
const instantiatedBaseType = thisArgument ? getTypeWithThisArgument(instantiateType(baseType, mapper), thisArgument) : baseType;
const instantiatedBaseType = thisArgument ? getTypeWithThisArgument(<ObjectType>instantiateType(baseType, mapper), thisArgument) : baseType;
addInheritedMembers(members, getPropertiesOfObjectType(instantiatedBaseType));
callSignatures = concatenate(callSignatures, getSignaturesOfType(instantiatedBaseType, SignatureKind.Call));
constructSignatures = concatenate(constructSignatures, getSignaturesOfType(instantiatedBaseType, SignatureKind.Construct));
@ -4139,7 +4139,7 @@ namespace ts {
numberIndexInfo = numberIndexInfo || getIndexInfoOfType(instantiatedBaseType, IndexKind.Number);
}
}
setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo);
setStructuredTypeMembers(type, members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo);
}
function resolveClassOrInterfaceMembers(type: InterfaceType): void {
@ -4286,7 +4286,7 @@ namespace ts {
const constructSignatures = getUnionSignatures(type.types, SignatureKind.Construct);
const stringIndexInfo = getUnionIndexInfo(type.types, IndexKind.String);
const numberIndexInfo = getUnionIndexInfo(type.types, IndexKind.Number);
setObjectTypeMembers(type, emptySymbols, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo);
setStructuredTypeMembers(type, emptySymbols, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo);
}
function intersectTypes(type1: Type, type2: Type): Type {
@ -4311,7 +4311,7 @@ namespace ts {
stringIndexInfo = intersectIndexInfos(stringIndexInfo, getIndexInfoOfType(t, IndexKind.String));
numberIndexInfo = intersectIndexInfos(numberIndexInfo, getIndexInfoOfType(t, IndexKind.Number));
}
setObjectTypeMembers(type, emptySymbols, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo);
setStructuredTypeMembers(type, emptySymbols, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo);
}
function resolveAnonymousTypeMembers(type: AnonymousType) {
@ -4322,7 +4322,7 @@ namespace ts {
const constructSignatures = instantiateList(getSignaturesOfType(type.target, SignatureKind.Construct), type.mapper, instantiateSignature);
const stringIndexInfo = instantiateIndexInfo(getIndexInfoOfType(type.target, IndexKind.String), type.mapper);
const numberIndexInfo = instantiateIndexInfo(getIndexInfoOfType(type.target, IndexKind.Number), type.mapper);
setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo);
setStructuredTypeMembers(type, members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo);
}
else if (symbol.flags & SymbolFlags.TypeLiteral) {
const members = symbol.members;
@ -4330,7 +4330,7 @@ namespace ts {
const constructSignatures = getSignaturesOfSymbol(members["__new"]);
const stringIndexInfo = getIndexInfoOfSymbol(symbol, IndexKind.String);
const numberIndexInfo = getIndexInfoOfSymbol(symbol, IndexKind.Number);
setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo);
setStructuredTypeMembers(type, members, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo);
}
else {
// Combinations of function, class, enum and module
@ -4352,7 +4352,7 @@ namespace ts {
}
}
const numberIndexInfo = symbol.flags & SymbolFlags.Enum ? enumNumberIndexInfo : undefined;
setObjectTypeMembers(type, members, emptyArray, constructSignatures, undefined, numberIndexInfo);
setStructuredTypeMembers(type, members, emptyArray, constructSignatures, undefined, numberIndexInfo);
// We resolve the members before computing the signatures because a signature may use
// typeof with a qualified name expression that circularly references the type we are
// in the process of resolving (see issue #6072). The temporarily empty signature list
@ -4363,7 +4363,7 @@ namespace ts {
}
}
function resolveStructuredTypeMembers(type: ObjectType): ResolvedType {
function resolveStructuredTypeMembers(type: StructuredType): ResolvedType {
if (!(<ResolvedType>type).members) {
if (type.flags & TypeFlags.Reference) {
resolveTypeReferenceMembers(<TypeReference>type);
@ -4569,7 +4569,7 @@ namespace ts {
function getPropertyOfType(type: Type, name: string): Symbol {
type = getApparentType(type);
if (type.flags & TypeFlags.ObjectType) {
const resolved = resolveStructuredTypeMembers(type);
const resolved = resolveStructuredTypeMembers(<ObjectType>type);
const symbol = resolved.members[name];
if (symbol && symbolIsValue(symbol)) {
return symbol;
@ -5316,7 +5316,7 @@ namespace ts {
/**
* Instantiates a global type that is generic with some element type, and returns that instantiation.
*/
function createTypeFromGenericGlobalType(genericGlobalType: GenericType, typeArguments: Type[]): Type {
function createTypeFromGenericGlobalType(genericGlobalType: GenericType, typeArguments: Type[]): ObjectType {
return genericGlobalType !== emptyGenericType ? createTypeReference(genericGlobalType, typeArguments) : emptyObjectType;
}
@ -5328,7 +5328,7 @@ namespace ts {
return createTypeFromGenericGlobalType(getGlobalIterableIteratorType(), [elementType]);
}
function createArrayType(elementType: Type): Type {
function createArrayType(elementType: Type): ObjectType {
return createTypeFromGenericGlobalType(globalArrayType, [elementType]);
}
@ -5568,7 +5568,7 @@ namespace ts {
let type = unionTypes[id];
if (!type) {
const propagatedFlags = getPropagatingFlagsOfTypes(types, /*excludeKinds*/ TypeFlags.Nullable);
type = unionTypes[id] = <UnionType>createObjectType(TypeFlags.Union | propagatedFlags);
type = unionTypes[id] = <UnionType>createType(TypeFlags.Union | propagatedFlags);
type.types = types;
type.aliasSymbol = aliasSymbol;
type.aliasTypeArguments = aliasTypeArguments;
@ -5639,7 +5639,7 @@ namespace ts {
let type = intersectionTypes[id];
if (!type) {
const propagatedFlags = getPropagatingFlagsOfTypes(typeSet, /*excludeKinds*/ TypeFlags.Nullable);
type = intersectionTypes[id] = <IntersectionType>createObjectType(TypeFlags.Intersection | propagatedFlags);
type = intersectionTypes[id] = <IntersectionType>createType(TypeFlags.Intersection | propagatedFlags);
type.types = typeSet;
type.aliasSymbol = aliasSymbol;
type.aliasTypeArguments = aliasTypeArguments;
@ -5980,7 +5980,7 @@ namespace ts {
function instantiateAnonymousType(type: AnonymousType, mapper: TypeMapper): ObjectType {
if (mapper.instantiations) {
const cachedType = mapper.instantiations[type.id];
const cachedType = <ObjectType>mapper.instantiations[type.id];
if (cachedType) {
return cachedType;
}
@ -6479,8 +6479,8 @@ namespace ts {
containingMessageChain?: DiagnosticMessageChain): boolean {
let errorInfo: DiagnosticMessageChain;
let sourceStack: ObjectType[];
let targetStack: ObjectType[];
let sourceStack: Type[];
let targetStack: Type[];
let maybeStack: Map<RelationComparisonResult>[];
let expandingFlags: number;
let depth = 0;
@ -6697,7 +6697,7 @@ namespace ts {
// type, a property is considered known if it is known in any constituent type.
function isKnownProperty(type: Type, name: string): boolean {
if (type.flags & TypeFlags.ObjectType) {
const resolved = resolveStructuredTypeMembers(type);
const resolved = resolveStructuredTypeMembers(<ObjectType>type);
if ((relation === assignableRelation || relation === comparableRelation) && (type === globalObjectType || isEmptyObjectType(resolved)) ||
resolved.stringIndexInfo ||
(resolved.numberIndexInfo && isNumericLiteralName(name)) ||
@ -17182,7 +17182,7 @@ namespace ts {
}
}
function checkBaseTypeAccessibility(type: ObjectType, node: ExpressionWithTypeArguments) {
function checkBaseTypeAccessibility(type: Type, node: ExpressionWithTypeArguments) {
const signatures = getSignaturesOfType(type, SignatureKind.Construct);
if (signatures.length) {
const declaration = signatures[0].declaration;

View File

@ -2699,6 +2699,7 @@ namespace ts {
// Object types (TypeFlags.ObjectType)
export interface ObjectType extends Type {
_objectTypeBrand: any;
isObjectLiteralPatternWithComputedProperties?: boolean;
}
@ -2753,6 +2754,8 @@ namespace ts {
export interface IntersectionType extends UnionOrIntersectionType { }
export type StructuredType = ObjectType | UnionType | IntersectionType;
/* @internal */
// An instantiated anonymous type has a target and a mapper
export interface AnonymousType extends ObjectType {