Skip to content

Commit b14d389

Browse files
committed
For 'T extends { [x: string]: XXX }' constraint of T[keyof T] is XXX
1 parent 02534cc commit b14d389

File tree

1 file changed

+18
-4
lines changed

1 file changed

+18
-4
lines changed

src/compiler/checker.ts

+18-4
Original file line numberDiff line numberDiff line change
@@ -8230,8 +8230,9 @@ namespace ts {
82308230
maybeTypeOfKind(type, TypeFlags.InstantiableNonPrimitive) ? getIndexTypeForGenericType(<InstantiableType | UnionOrIntersectionType>type, includeDeclaredTypes) :
82318231
getObjectFlags(type) & ObjectFlags.Mapped ? getConstraintTypeFromMappedType(<MappedType>type) :
82328232
type === wildcardType ? wildcardType :
8233-
type.flags & TypeFlags.Any || getIndexInfoOfType(type, IndexKind.String) ? keyofConstraintType :
8234-
keyofStringsOnly ? getLiteralTypeFromPropertyNames(type, TypeFlags.StringLiteral) :
8233+
type.flags & TypeFlags.Any ? keyofConstraintType :
8234+
keyofStringsOnly ? getIndexInfoOfType(type, IndexKind.String) ? stringType : getLiteralTypeFromPropertyNames(type, TypeFlags.StringLiteral) :
8235+
getIndexInfoOfType(type, IndexKind.String) ? getUnionType([stringType, numberType, getLiteralTypeFromPropertyNames(type, TypeFlags.UniqueESSymbol)]) :
82358236
getNonEnumNumberIndexInfo(type) ? getUnionType([numberType, getLiteralTypeFromPropertyNames(type, TypeFlags.StringLiteral | TypeFlags.UniqueESSymbol)]) :
82368237
getLiteralTypeFromPropertyNames(type, TypeFlags.StringOrNumberLiteralOrUnique);
82378238
}
@@ -8303,7 +8304,11 @@ namespace ts {
83038304
getIndexInfoOfType(objectType, IndexKind.String) ||
83048305
undefined;
83058306
if (indexInfo) {
8306-
if (accessExpression && indexInfo.isReadonly && (isAssignmentTarget(accessExpression) || isDeleteTarget(accessExpression))) {
8307+
if (accessNode && !isTypeAssignableToKind(indexType, TypeFlags.String | TypeFlags.Number)) {
8308+
const indexNode = accessNode.kind === SyntaxKind.ElementAccessExpression ? accessNode.argumentExpression : accessNode.indexType;
8309+
error(indexNode, Diagnostics.Type_0_cannot_be_used_as_an_index_type, typeToString(indexType));
8310+
}
8311+
else if (accessExpression && indexInfo.isReadonly && (isAssignmentTarget(accessExpression) || isDeleteTarget(accessExpression))) {
83078312
error(accessExpression, Diagnostics.Index_signature_in_type_0_only_permits_reading, typeToString(objectType));
83088313
}
83098314
return indexInfo.type;
@@ -20055,6 +20060,15 @@ namespace ts {
2005520060
return widened;
2005620061
}
2005720062

20063+
function isTypeParameterWithKeyofConstraint(type: Type) {
20064+
if (type.flags & TypeFlags.TypeParameter) {
20065+
const constraintDeclaration = getConstraintDeclaration(<TypeParameter>type);
20066+
return constraintDeclaration && constraintDeclaration.kind === SyntaxKind.TypeOperator &&
20067+
(<TypeOperatorNode>constraintDeclaration).operator === SyntaxKind.KeyOfKeyword;
20068+
}
20069+
return false;
20070+
}
20071+
2005820072
function isLiteralOfContextualType(candidateType: Type, contextualType: Type): boolean {
2005920073
if (contextualType) {
2006020074
if (contextualType.flags & TypeFlags.UnionOrIntersection) {
@@ -20066,7 +20080,7 @@ namespace ts {
2006620080
// this a literal context for literals of that primitive type. For example, given a
2006720081
// type parameter 'T extends string', infer string literal types for T.
2006820082
const constraint = getBaseConstraintOfType(contextualType) || emptyObjectType;
20069-
return constraint === keyofConstraintType && maybeTypeOfKind(candidateType, TypeFlags.StringLiteral | TypeFlags.NumberLiteral | TypeFlags.UniqueESSymbol) ||
20083+
return isTypeParameterWithKeyofConstraint(contextualType) && maybeTypeOfKind(candidateType, TypeFlags.StringLiteral | TypeFlags.NumberLiteral | TypeFlags.UniqueESSymbol) ||
2007020084
constraint.flags & TypeFlags.String && maybeTypeOfKind(candidateType, TypeFlags.StringLiteral) ||
2007120085
constraint.flags & TypeFlags.Number && maybeTypeOfKind(candidateType, TypeFlags.NumberLiteral) ||
2007220086
constraint.flags & TypeFlags.Boolean && maybeTypeOfKind(candidateType, TypeFlags.BooleanLiteral) ||

0 commit comments

Comments
 (0)