Introduce PropertyNameType

This commit is contained in:
Anders Hejlsberg 2016-10-25 06:35:35 -07:00
parent ad88109420
commit 07478aae14
2 changed files with 32 additions and 11 deletions

View File

@ -2219,6 +2219,11 @@ namespace ts {
else if (type.flags & TypeFlags.StringOrNumberLiteral) {
writer.writeStringLiteral(literalTypeToString(<LiteralType>type));
}
else if (type.flags & TypeFlags.PropertyName) {
writer.writeKeyword("keyof");
writeSpace(writer);
writeType((<PropertyNameType>type).type, TypeFormatFlags.None);
}
else {
// Should never get here
// { ... }
@ -5667,18 +5672,24 @@ namespace ts {
return startsWith(prop.name, "__@") ? neverType : getLiteralTypeForText(TypeFlags.StringLiteral, unescapeIdentifier(prop.name));
}
function getKeyOfType(type: Type): Type {
if (getIndexInfoOfType(type, IndexKind.String)) {
return getUnionType([stringType, numberType]);
function getPropertyNameTypeForTypeParameter(type: TypeParameter) {
if (!type.resolvedPropertyNameType) {
type.resolvedPropertyNameType = <PropertyNameType>createType(TypeFlags.PropertyName);
type.resolvedPropertyNameType.type = type;
}
const propKeysType = getUnionType(map(getPropertiesOfType(type), getLiteralTypeFromPropertyName));
return getIndexInfoOfType(type, IndexKind.Number) ? getUnionType([numberType, propKeysType]) : propKeysType;
return type.resolvedPropertyNameType;
}
function getPropertyNameType(type: Type): Type {
return type.flags & TypeFlags.TypeParameter ?
getPropertyNameTypeForTypeParameter(<TypeParameter>type) :
getUnionType(map(getPropertiesOfType(type), getLiteralTypeFromPropertyName));
}
function getTypeFromTypeOperatorNode(node: TypeOperatorNode) {
const links = getNodeLinks(node);
if (!links.resolvedType) {
links.resolvedType = getKeyOfType(getTypeFromTypeNodeNoAlias(node.type));
links.resolvedType = getPropertyNameType(getTypeFromTypeNodeNoAlias(node.type));
}
return links.resolvedType;
}
@ -6105,6 +6116,9 @@ namespace ts {
if (type.flags & TypeFlags.Intersection) {
return getIntersectionType(instantiateList((<IntersectionType>type).types, mapper, instantiateType), type.aliasSymbol, mapper.targetTypes);
}
if (type.flags & TypeFlags.PropertyName) {
return getPropertyNameType(instantiateType((<PropertyNameType>type).type, mapper));
}
}
return type;
}

View File

@ -2623,14 +2623,15 @@ namespace ts {
Object = 1 << 15, // Object type
Union = 1 << 16, // Union (T | U)
Intersection = 1 << 17, // Intersection (T & U)
PropertyName = 1 << 18, // keyof T
/* @internal */
FreshLiteral = 1 << 18, // Fresh literal type
FreshLiteral = 1 << 19, // Fresh literal type
/* @internal */
ContainsWideningType = 1 << 19, // Type is or contains undefined or null widening type
ContainsWideningType = 1 << 20, // Type is or contains undefined or null widening type
/* @internal */
ContainsObjectLiteral = 1 << 20, // Type is or contains object literal type
ContainsObjectLiteral = 1 << 21, // Type is or contains object literal type
/* @internal */
ContainsAnyFunctionType = 1 << 21, // Type is or contains object literal type
ContainsAnyFunctionType = 1 << 22, // Type is or contains object literal type
/* @internal */
Nullable = Undefined | Null,
@ -2643,7 +2644,7 @@ namespace ts {
Intrinsic = Any | String | Number | Boolean | BooleanLiteral | ESSymbol | Void | Undefined | Null | Never,
/* @internal */
Primitive = String | Number | Boolean | Enum | ESSymbol | Void | Undefined | Null | Literal,
StringLike = String | StringLiteral,
StringLike = String | StringLiteral | PropertyName,
NumberLike = Number | NumberLiteral | Enum | EnumLiteral,
BooleanLike = Boolean | BooleanLiteral,
EnumLike = Enum | EnumLiteral,
@ -2816,9 +2817,15 @@ namespace ts {
/* @internal */
resolvedApparentType: Type;
/* @internal */
resolvedPropertyNameType: PropertyNameType;
/* @internal */
isThisType?: boolean;
}
export interface PropertyNameType extends Type {
type: TypeParameter;
}
export const enum SignatureKind {
Call,
Construct,