mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-10 15:25:54 -06:00
Consistent handling of string-like and number-like values in expressions
This commit is contained in:
parent
1ce32d91a4
commit
8573850308
@ -5621,7 +5621,7 @@ module ts {
|
||||
}
|
||||
|
||||
var isConstEnum = isConstEnumObjectType(objectType);
|
||||
if (isConstEnum &&
|
||||
if (isConstEnum &&
|
||||
(!node.argumentExpression || node.argumentExpression.kind !== SyntaxKind.StringLiteral)) {
|
||||
error(node.argumentExpression, Diagnostics.A_const_enum_member_can_only_be_accessed_using_a_string_literal);
|
||||
return unknownType;
|
||||
@ -5653,10 +5653,10 @@ module ts {
|
||||
}
|
||||
|
||||
// Check for compatible indexer types.
|
||||
if (indexType.flags & (TypeFlags.Any | TypeFlags.StringLike | TypeFlags.NumberLike) || isTypeAssignableTo(indexType, stringOrNumberType)) {
|
||||
if (isTypeOfKind(indexType, TypeFlags.Any | TypeFlags.StringLike | TypeFlags.NumberLike)) {
|
||||
|
||||
// Try to use a number indexer.
|
||||
if (indexType.flags & (TypeFlags.Any | TypeFlags.NumberLike) || isTypeAssignableTo(indexType, numberType)) {
|
||||
if (isTypeOfKind(indexType, TypeFlags.Any | TypeFlags.NumberLike)) {
|
||||
var numberIndexType = getIndexTypeOfType(objectType, IndexKind.Number);
|
||||
if (numberIndexType) {
|
||||
return numberIndexType;
|
||||
@ -6557,7 +6557,7 @@ module ts {
|
||||
}
|
||||
|
||||
function checkArithmeticOperandType(operand: Node, type: Type, diagnostic: DiagnosticMessage): boolean {
|
||||
if (!(type.flags & (TypeFlags.Any | TypeFlags.NumberLike))) {
|
||||
if (!isTypeOfKind(type, TypeFlags.Any | TypeFlags.NumberLike)) {
|
||||
error(operand, diagnostic);
|
||||
return false;
|
||||
}
|
||||
@ -6708,12 +6708,21 @@ module ts {
|
||||
return numberType;
|
||||
}
|
||||
|
||||
// Return true if type an object type, a type parameter, or a union type composed of only those kinds of types
|
||||
function isStructuredType(type: Type): boolean {
|
||||
if (type.flags & TypeFlags.Union) {
|
||||
return !forEach((<UnionType>type).types, t => !isStructuredType(t));
|
||||
// Return true if type has the given flags, or is a union type composed of types that all have those flags
|
||||
function isTypeOfKind(type: Type, kind: TypeFlags): boolean {
|
||||
if (type.flags & kind) {
|
||||
return true;
|
||||
}
|
||||
return (type.flags & (TypeFlags.ObjectType | TypeFlags.TypeParameter)) !== 0;
|
||||
if (type.flags & TypeFlags.Union) {
|
||||
var types = (<UnionType>type).types;
|
||||
for (var i = 0; i < types.length; i++) {
|
||||
if (!(types[i].flags & kind)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function isConstEnumObjectType(type: Type): boolean {
|
||||
@ -6730,7 +6739,7 @@ module ts {
|
||||
// and the right operand to be of type Any or a subtype of the 'Function' interface type.
|
||||
// The result is always of the Boolean primitive type.
|
||||
// NOTE: do not raise error if leftType is unknown as related error was already reported
|
||||
if (!(leftType.flags & TypeFlags.Any || isStructuredType(leftType))) {
|
||||
if (!isTypeOfKind(leftType, TypeFlags.Any | TypeFlags.ObjectType | TypeFlags.TypeParameter)) {
|
||||
error(node.left, Diagnostics.The_left_hand_side_of_an_instanceof_expression_must_be_of_type_any_an_object_type_or_a_type_parameter);
|
||||
}
|
||||
// NOTE: do not raise error if right is unknown as related error was already reported
|
||||
@ -6745,10 +6754,10 @@ module ts {
|
||||
// The in operator requires the left operand to be of type Any, the String primitive type, or the Number primitive type,
|
||||
// and the right operand to be of type Any, an object type, or a type parameter type.
|
||||
// The result is always of the Boolean primitive type.
|
||||
if (leftType !== anyType && leftType !== stringType && leftType !== numberType) {
|
||||
if (!isTypeOfKind(leftType, TypeFlags.Any | TypeFlags.StringLike | TypeFlags.NumberLike)) {
|
||||
error(node.left, Diagnostics.The_left_hand_side_of_an_in_expression_must_be_of_types_any_string_or_number);
|
||||
}
|
||||
if (!(rightType.flags & TypeFlags.Any || isStructuredType(rightType))) {
|
||||
if (!isTypeOfKind(rightType, TypeFlags.Any | TypeFlags.ObjectType | TypeFlags.TypeParameter)) {
|
||||
error(node.right, Diagnostics.The_right_hand_side_of_an_in_expression_must_be_of_type_any_an_object_type_or_a_type_parameter);
|
||||
}
|
||||
return booleanType;
|
||||
@ -6909,16 +6918,16 @@ module ts {
|
||||
if (rightType.flags & (TypeFlags.Undefined | TypeFlags.Null)) rightType = leftType;
|
||||
|
||||
var resultType: Type;
|
||||
if (leftType.flags & TypeFlags.NumberLike && rightType.flags & TypeFlags.NumberLike) {
|
||||
if (isTypeOfKind(leftType, TypeFlags.NumberLike) && isTypeOfKind(rightType, TypeFlags.NumberLike)) {
|
||||
// Operands of an enum type are treated as having the primitive type Number.
|
||||
// If both operands are of the Number primitive type, the result is of the Number primitive type.
|
||||
resultType = numberType;
|
||||
}
|
||||
else if (leftType.flags & TypeFlags.StringLike || rightType.flags & TypeFlags.StringLike) {
|
||||
else if (isTypeOfKind(leftType, TypeFlags.StringLike) || isTypeOfKind(rightType, TypeFlags.StringLike)) {
|
||||
// If one or both operands are of the String primitive type, the result is of the String primitive type.
|
||||
resultType = stringType;
|
||||
}
|
||||
else if (leftType.flags & TypeFlags.Any || leftType === unknownType || rightType.flags & TypeFlags.Any || rightType === unknownType) {
|
||||
else if (leftType.flags & TypeFlags.Any || rightType.flags & TypeFlags.Any) {
|
||||
// Otherwise, the result is of type Any.
|
||||
// NOTE: unknown type here denotes error type. Old compiler treated this case as any type so do we.
|
||||
resultType = anyType;
|
||||
@ -8274,7 +8283,7 @@ module ts {
|
||||
var exprType = checkExpression(node.expression);
|
||||
// unknownType is returned i.e. if node.expression is identifier whose name cannot be resolved
|
||||
// in this case error about missing name is already reported - do not report extra one
|
||||
if (!(exprType.flags & TypeFlags.Any || isStructuredType(exprType))) {
|
||||
if (!isTypeOfKind(exprType, TypeFlags.Any | TypeFlags.ObjectType | TypeFlags.TypeParameter)) {
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user