@@ -7556,11 +7556,11 @@ namespace ts {
7556
7556
return getTypeOfSymbol(prop);
7557
7557
}
7558
7558
}
7559
- if (isTypeAnyOrAllConstituentTypesHaveKind (indexType, TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbol)) {
7559
+ if (!(indexType.flags & TypeFlags.Nullable) && isTypeAssignableToKind (indexType, TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbol)) {
7560
7560
if (isTypeAny(objectType)) {
7561
7561
return anyType;
7562
7562
}
7563
- const indexInfo = isTypeAnyOrAllConstituentTypesHaveKind (indexType, TypeFlags.NumberLike) && getIndexInfoOfType(objectType, IndexKind.Number) ||
7563
+ const indexInfo = isTypeAssignableToKind (indexType, TypeFlags.NumberLike) && getIndexInfoOfType(objectType, IndexKind.Number) ||
7564
7564
getIndexInfoOfType(objectType, IndexKind.String) ||
7565
7565
undefined;
7566
7566
if (indexInfo) {
@@ -11384,7 +11384,7 @@ namespace ts {
11384
11384
(<BinaryExpression>parent.parent).operatorToken.kind === SyntaxKind.EqualsToken &&
11385
11385
(<BinaryExpression>parent.parent).left === parent &&
11386
11386
!isAssignmentTarget(parent.parent) &&
11387
- isTypeAnyOrAllConstituentTypesHaveKind (getTypeOfExpression((<ElementAccessExpression>parent).argumentExpression), TypeFlags.NumberLike | TypeFlags.Undefined );
11387
+ isTypeAssignableToKind (getTypeOfExpression((<ElementAccessExpression>parent).argumentExpression), TypeFlags.NumberLike);
11388
11388
return isLengthPushOrUnshift || isElementAssignment;
11389
11389
}
11390
11390
@@ -11556,7 +11556,7 @@ namespace ts {
11556
11556
}
11557
11557
else {
11558
11558
const indexType = getTypeOfExpression((<ElementAccessExpression>(<BinaryExpression>node).left).argumentExpression);
11559
- if (isTypeAnyOrAllConstituentTypesHaveKind (indexType, TypeFlags.NumberLike | TypeFlags.Undefined )) {
11559
+ if (isTypeAssignableToKind (indexType, TypeFlags.NumberLike)) {
11560
11560
evolvedType = addEvolvingArrayElementType(evolvedType, (<BinaryExpression>node).right);
11561
11561
}
11562
11562
}
@@ -13398,11 +13398,7 @@ namespace ts {
13398
13398
function isNumericComputedName(name: ComputedPropertyName): boolean {
13399
13399
// It seems odd to consider an expression of type Any to result in a numeric name,
13400
13400
// but this behavior is consistent with checkIndexedAccess
13401
- return isTypeAnyOrAllConstituentTypesHaveKind(checkComputedPropertyName(name), TypeFlags.NumberLike);
13402
- }
13403
-
13404
- function isTypeAnyOrAllConstituentTypesHaveKind(type: Type, kind: TypeFlags): boolean {
13405
- return isTypeAny(type) || isTypeOfKind(type, kind);
13401
+ return isTypeAssignableToKind(checkComputedPropertyName(name), TypeFlags.NumberLike);
13406
13402
}
13407
13403
13408
13404
function isInfinityOrNaNString(name: string | __String): boolean {
@@ -13438,10 +13434,11 @@ namespace ts {
13438
13434
const links = getNodeLinks(node.expression);
13439
13435
if (!links.resolvedType) {
13440
13436
links.resolvedType = checkExpression(node.expression);
13441
-
13442
13437
// This will allow types number, string, symbol or any. It will also allow enums, the unknown
13443
13438
// type, and any union of these types (like string | number).
13444
- if (!isTypeAnyOrAllConstituentTypesHaveKind(links.resolvedType, TypeFlags.NumberLike | TypeFlags.StringLike | TypeFlags.ESSymbol)) {
13439
+ if (links.resolvedType.flags & TypeFlags.Nullable ||
13440
+ !isTypeAssignableToKind(links.resolvedType, TypeFlags.StringLike | TypeFlags.NumberLike | TypeFlags.ESSymbol) &&
13441
+ !isTypeAssignableTo(links.resolvedType, getUnionType([stringType, numberType, esSymbolType]))) {
13445
13442
error(node, Diagnostics.A_computed_property_name_must_be_of_type_string_number_symbol_or_any);
13446
13443
}
13447
13444
else {
@@ -15546,7 +15543,7 @@ namespace ts {
15546
15543
15547
15544
case SyntaxKind.ComputedPropertyName:
15548
15545
const nameType = checkComputedPropertyName(element.name);
15549
- if (isTypeOfKind (nameType, TypeFlags.ESSymbol)) {
15546
+ if (isTypeAssignableToKind (nameType, TypeFlags.ESSymbol)) {
15550
15547
return nameType;
15551
15548
}
15552
15549
else {
@@ -16936,7 +16933,7 @@ namespace ts {
16936
16933
}
16937
16934
16938
16935
function checkArithmeticOperandType(operand: Node, type: Type, diagnostic: DiagnosticMessage): boolean {
16939
- if (!isTypeAnyOrAllConstituentTypesHaveKind (type, TypeFlags.NumberLike)) {
16936
+ if (!isTypeAssignableToKind (type, TypeFlags.NumberLike)) {
16940
16937
error(operand, diagnostic);
16941
16938
return false;
16942
16939
}
@@ -17114,31 +17111,22 @@ namespace ts {
17114
17111
return false;
17115
17112
}
17116
17113
17117
- // Return true if type is of the given kind. A union type is of a given kind if all constituent types
17118
- // are of the given kind. An intersection type is of a given kind if at least one constituent type is
17119
- // of the given kind.
17120
- function isTypeOfKind(type: Type, kind: TypeFlags): boolean {
17121
- if (type.flags & kind) {
17114
+ function isTypeAssignableToKind(source: Type, kind: TypeFlags, strict?: boolean): boolean {
17115
+ if (source.flags & kind) {
17122
17116
return true;
17123
17117
}
17124
- if (type.flags & TypeFlags.Union) {
17125
- const types = (<UnionOrIntersectionType>type).types;
17126
- for (const t of types) {
17127
- if (!isTypeOfKind(t, kind)) {
17128
- return false;
17129
- }
17130
- }
17131
- return true;
17132
- }
17133
- if (type.flags & TypeFlags.Intersection) {
17134
- const types = (<UnionOrIntersectionType>type).types;
17135
- for (const t of types) {
17136
- if (isTypeOfKind(t, kind)) {
17137
- return true;
17138
- }
17139
- }
17118
+ if (strict && source.flags & (TypeFlags.Any | TypeFlags.Void | TypeFlags.Undefined | TypeFlags.Null)) {
17119
+ return false;
17140
17120
}
17141
- return false;
17121
+ return (kind & TypeFlags.NumberLike && isTypeAssignableTo(source, numberType)) ||
17122
+ (kind & TypeFlags.StringLike && isTypeAssignableTo(source, stringType)) ||
17123
+ (kind & TypeFlags.BooleanLike && isTypeAssignableTo(source, booleanType)) ||
17124
+ (kind & TypeFlags.Void && isTypeAssignableTo(source, voidType)) ||
17125
+ (kind & TypeFlags.Never && isTypeAssignableTo(source, neverType)) ||
17126
+ (kind & TypeFlags.Null && isTypeAssignableTo(source, nullType)) ||
17127
+ (kind & TypeFlags.Undefined && isTypeAssignableTo(source, undefinedType)) ||
17128
+ (kind & TypeFlags.ESSymbol && isTypeAssignableTo(source, esSymbolType)) ||
17129
+ (kind & TypeFlags.NonPrimitive && isTypeAssignableTo(source, nonPrimitiveType));
17142
17130
}
17143
17131
17144
17132
function isConstEnumObjectType(type: Type): boolean {
@@ -17158,7 +17146,7 @@ namespace ts {
17158
17146
// and the right operand to be of type Any, a subtype of the 'Function' interface type, or have a call or construct signature.
17159
17147
// The result is always of the Boolean primitive type.
17160
17148
// NOTE: do not raise error if leftType is unknown as related error was already reported
17161
- if (isTypeOfKind (leftType, TypeFlags.Primitive)) {
17149
+ if (!isTypeAny(leftType) && isTypeAssignableToKind (leftType, TypeFlags.Primitive)) {
17162
17150
error(left, Diagnostics.The_left_hand_side_of_an_instanceof_expression_must_be_of_type_any_an_object_type_or_a_type_parameter);
17163
17151
}
17164
17152
// NOTE: do not raise error if right is unknown as related error was already reported
@@ -17181,10 +17169,10 @@ namespace ts {
17181
17169
// The in operator requires the left operand to be of type Any, the String primitive type, or the Number primitive type,
17182
17170
// and the right operand to be of type Any, an object type, or a type parameter type.
17183
17171
// The result is always of the Boolean primitive type.
17184
- if (!(isTypeComparableTo(leftType, stringType) || isTypeOfKind (leftType, TypeFlags.NumberLike | TypeFlags.ESSymbol))) {
17172
+ if (!(isTypeComparableTo(leftType, stringType) || isTypeAssignableToKind (leftType, TypeFlags.NumberLike | TypeFlags.ESSymbol))) {
17185
17173
error(left, Diagnostics.The_left_hand_side_of_an_in_expression_must_be_of_type_any_string_number_or_symbol);
17186
17174
}
17187
- if (!isTypeAnyOrAllConstituentTypesHaveKind (rightType, TypeFlags.Object | TypeFlags.TypeVariable | TypeFlags.NonPrimitive )) {
17175
+ if (!isTypeAssignableToKind (rightType, TypeFlags.NonPrimitive | TypeFlags.TypeVariable)) {
17188
17176
error(right, Diagnostics.The_right_hand_side_of_an_in_expression_must_be_of_type_any_an_object_type_or_a_type_parameter);
17189
17177
}
17190
17178
return booleanType;
@@ -17493,32 +17481,30 @@ namespace ts {
17493
17481
return silentNeverType;
17494
17482
}
17495
17483
17496
- if (!isTypeOfKind (leftType, TypeFlags.Any | TypeFlags. StringLike) && !isTypeOfKind (rightType, TypeFlags.Any | TypeFlags.StringLike)) {
17484
+ if (!isTypeAssignableToKind (leftType, TypeFlags.StringLike) && !isTypeAssignableToKind (rightType, TypeFlags.StringLike)) {
17497
17485
leftType = checkNonNullType(leftType, left);
17498
17486
rightType = checkNonNullType(rightType, right);
17499
17487
}
17500
17488
17501
17489
let resultType: Type;
17502
- if (isTypeOfKind (leftType, TypeFlags.NumberLike) && isTypeOfKind (rightType, TypeFlags.NumberLike)) {
17490
+ if (isTypeAssignableToKind (leftType, TypeFlags.NumberLike, /*strict*/ true ) && isTypeAssignableToKind (rightType, TypeFlags.NumberLike, /*strict*/ true )) {
17503
17491
// Operands of an enum type are treated as having the primitive type Number.
17504
17492
// If both operands are of the Number primitive type, the result is of the Number primitive type.
17505
17493
resultType = numberType;
17506
17494
}
17507
- else {
17508
- if (isTypeOfKind(leftType, TypeFlags.StringLike) || isTypeOfKind(rightType, TypeFlags.StringLike)) {
17495
+ else if (isTypeAssignableToKind(leftType, TypeFlags.StringLike, /*strict*/ true) || isTypeAssignableToKind(rightType, TypeFlags.StringLike, /*strict*/ true)) {
17509
17496
// If one or both operands are of the String primitive type, the result is of the String primitive type.
17510
17497
resultType = stringType;
17511
- }
17512
- else if (isTypeAny(leftType) || isTypeAny(rightType)) {
17513
- // Otherwise, the result is of type Any.
17514
- // NOTE: unknown type here denotes error type. Old compiler treated this case as any type so do we.
17515
- resultType = leftType === unknownType || rightType === unknownType ? unknownType : anyType;
17516
- }
17498
+ }
17499
+ else if (isTypeAny(leftType) || isTypeAny(rightType)) {
17500
+ // Otherwise, the result is of type Any.
17501
+ // NOTE: unknown type here denotes error type. Old compiler treated this case as any type so do we.
17502
+ resultType = leftType === unknownType || rightType === unknownType ? unknownType : anyType;
17503
+ }
17517
17504
17518
- // Symbols are not allowed at all in arithmetic expressions
17519
- if (resultType && !checkForDisallowedESSymbolOperand(operator)) {
17520
- return resultType;
17521
- }
17505
+ // Symbols are not allowed at all in arithmetic expressions
17506
+ if (resultType && !checkForDisallowedESSymbolOperand(operator)) {
17507
+ return resultType;
17522
17508
}
17523
17509
17524
17510
if (!resultType) {
@@ -18732,7 +18718,7 @@ namespace ts {
18732
18718
}
18733
18719
// Check if we're indexing with a numeric type and the object type is a generic
18734
18720
// type with a constraint that has a numeric index signature.
18735
- if (maybeTypeOfKind(objectType, TypeFlags.TypeVariable) && isTypeOfKind (indexType, TypeFlags.NumberLike)) {
18721
+ if (maybeTypeOfKind(objectType, TypeFlags.TypeVariable) && isTypeAssignableToKind (indexType, TypeFlags.NumberLike)) {
18736
18722
const constraint = getBaseConstraintOfType(objectType);
18737
18723
if (constraint && getIndexInfoOfType(constraint, IndexKind.Number)) {
18738
18724
return type;
@@ -20439,7 +20425,7 @@ namespace ts {
20439
20425
20440
20426
// unknownType is returned i.e. if node.expression is identifier whose name cannot be resolved
20441
20427
// in this case error about missing name is already reported - do not report extra one
20442
- if (!isTypeAnyOrAllConstituentTypesHaveKind (rightType, TypeFlags.Object | TypeFlags.TypeVariable | TypeFlags.NonPrimitive )) {
20428
+ if (!isTypeAssignableToKind (rightType, TypeFlags.NonPrimitive | TypeFlags.TypeVariable)) {
20443
20429
error(node.expression, Diagnostics.The_right_hand_side_of_a_for_in_statement_must_be_of_type_any_an_object_type_or_a_type_parameter);
20444
20430
}
20445
20431
@@ -23426,22 +23412,22 @@ namespace ts {
23426
23412
else if (type.flags & TypeFlags.Any) {
23427
23413
return TypeReferenceSerializationKind.ObjectType;
23428
23414
}
23429
- else if (isTypeOfKind (type, TypeFlags.Void | TypeFlags.Nullable | TypeFlags.Never)) {
23415
+ else if (isTypeAssignableToKind (type, TypeFlags.Void | TypeFlags.Nullable | TypeFlags.Never)) {
23430
23416
return TypeReferenceSerializationKind.VoidNullableOrNeverType;
23431
23417
}
23432
- else if (isTypeOfKind (type, TypeFlags.BooleanLike)) {
23418
+ else if (isTypeAssignableToKind (type, TypeFlags.BooleanLike)) {
23433
23419
return TypeReferenceSerializationKind.BooleanType;
23434
23420
}
23435
- else if (isTypeOfKind (type, TypeFlags.NumberLike)) {
23421
+ else if (isTypeAssignableToKind (type, TypeFlags.NumberLike)) {
23436
23422
return TypeReferenceSerializationKind.NumberLikeType;
23437
23423
}
23438
- else if (isTypeOfKind (type, TypeFlags.StringLike)) {
23424
+ else if (isTypeAssignableToKind (type, TypeFlags.StringLike)) {
23439
23425
return TypeReferenceSerializationKind.StringLikeType;
23440
23426
}
23441
23427
else if (isTupleType(type)) {
23442
23428
return TypeReferenceSerializationKind.ArrayLikeType;
23443
23429
}
23444
- else if (isTypeOfKind (type, TypeFlags.ESSymbol)) {
23430
+ else if (isTypeAssignableToKind (type, TypeFlags.ESSymbol)) {
23445
23431
return TypeReferenceSerializationKind.ESSymbolType;
23446
23432
}
23447
23433
else if (isFunctionType(type)) {
0 commit comments