Only include unique symbols when getting index types for access checks (#23145)

* Only include unique symbols when getting index types for access checks

* Filter all nonstrings

* Inline ternary
This commit is contained in:
Wesley Wigham
2018-04-04 18:03:21 -07:00
committed by GitHub
parent 7dc91476a1
commit de669cf827
7 changed files with 322 additions and 13 deletions

View File

@@ -8114,12 +8114,16 @@ namespace ts {
return links.resolvedType;
}
function getIndexTypeForGenericType(type: InstantiableType | UnionOrIntersectionType) {
if (!type.resolvedIndexType) {
type.resolvedIndexType = <IndexType>createType(TypeFlags.Index);
type.resolvedIndexType.type = type;
function getIndexTypeForGenericType(type: InstantiableType | UnionOrIntersectionType, includeDeclaredTypes?: boolean) {
const cacheLocation = includeDeclaredTypes ? "resolvedDeclaredIndexType" : "resolvedIndexType";
if (!type[cacheLocation]) {
type[cacheLocation] = <IndexType>createType(TypeFlags.Index);
type[cacheLocation].type = type;
if (includeDeclaredTypes) {
type[cacheLocation].isDeclaredType = true;
}
}
return type.resolvedIndexType;
return type[cacheLocation];
}
function getLiteralTypeFromPropertyName(prop: Symbol) {
@@ -8137,17 +8141,22 @@ namespace ts {
return links.nameType;
}
function getLiteralTypeFromPropertyNames(type: Type) {
return getUnionType(map(getPropertiesOfType(type), getLiteralTypeFromPropertyName));
function isTypeString(type: Type) {
return isTypeAssignableToKind(type, TypeFlags.StringLike);
}
function getIndexType(type: Type): Type {
return type.flags & TypeFlags.Intersection ? getUnionType(map((<IntersectionType>type).types, t => getIndexType(t))) :
maybeTypeOfKind(type, TypeFlags.InstantiableNonPrimitive) ? getIndexTypeForGenericType(<InstantiableType | UnionOrIntersectionType>type) :
function getLiteralTypeFromPropertyNames(type: Type, includeDeclaredTypes?: boolean) {
const originalKeys = map(getPropertiesOfType(type), getLiteralTypeFromPropertyName);
return getUnionType(includeDeclaredTypes ? originalKeys : filter(originalKeys, isTypeString));
}
function getIndexType(type: Type, includeDeclaredTypes?: boolean): Type {
return type.flags & TypeFlags.Intersection ? getUnionType(map((<IntersectionType>type).types, t => getIndexType(t, includeDeclaredTypes))) :
maybeTypeOfKind(type, TypeFlags.InstantiableNonPrimitive) ? getIndexTypeForGenericType(<InstantiableType | UnionOrIntersectionType>type, includeDeclaredTypes) :
getObjectFlags(type) & ObjectFlags.Mapped ? getConstraintTypeFromMappedType(<MappedType>type) :
type === wildcardType ? wildcardType :
type.flags & TypeFlags.Any || getIndexInfoOfType(type, IndexKind.String) ? stringType :
getLiteralTypeFromPropertyNames(type);
getLiteralTypeFromPropertyNames(type, includeDeclaredTypes);
}
function getIndexTypeOrString(type: Type): Type {
@@ -10323,7 +10332,7 @@ namespace ts {
// constraint of T.
const constraint = getConstraintForRelation((<IndexType>target).type);
if (constraint) {
if (result = isRelatedTo(source, getIndexType(constraint), reportErrors)) {
if (result = isRelatedTo(source, getIndexType(constraint, (target as IndexType).isDeclaredType), reportErrors)) {
return result;
}
}
@@ -20871,7 +20880,7 @@ namespace ts {
// Check if the index type is assignable to 'keyof T' for the object type.
const objectType = (<IndexedAccessType>type).objectType;
const indexType = (<IndexedAccessType>type).indexType;
if (isTypeAssignableTo(indexType, getIndexType(objectType))) {
if (isTypeAssignableTo(indexType, getIndexType(objectType, /*includeDeclaredTypes*/ true))) {
if (accessNode.kind === SyntaxKind.ElementAccessExpression && isAssignmentTarget(accessNode) &&
getObjectFlags(objectType) & ObjectFlags.Mapped && getMappedTypeModifiers(<MappedType>objectType) & MappedTypeModifiers.IncludeReadonly) {
error(accessNode, Diagnostics.Index_signature_in_type_0_only_permits_reading, typeToString(objectType));

View File

@@ -3753,6 +3753,8 @@ namespace ts {
/* @internal */
resolvedIndexType: IndexType;
/* @internal */
resolvedDeclaredIndexType: IndexType;
/* @internal */
resolvedBaseConstraint: Type;
/* @internal */
couldContainTypeVariables: boolean;
@@ -3839,6 +3841,8 @@ namespace ts {
resolvedBaseConstraint?: Type;
/* @internal */
resolvedIndexType?: IndexType;
/* @internal */
resolvedDeclaredIndexType?: IndexType;
}
// Type parameters (TypeFlags.TypeParameter)
@@ -3870,6 +3874,8 @@ namespace ts {
// keyof T types (TypeFlags.Index)
export interface IndexType extends InstantiableType {
/* @internal */
isDeclaredType?: boolean;
type: InstantiableType | UnionOrIntersectionType;
}