From 8dbfe1ca631111e28a59b62e1ddc941ea6fe2e3f Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 6 Nov 2015 12:58:03 -0800 Subject: [PATCH] Added specific checks for comparing stringlike types. --- src/compiler/checker.ts | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 50b826c1d14..3bbc27d71b0 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -9400,7 +9400,12 @@ namespace ts { let targetType = getTypeFromTypeNode(node.type); if (produceDiagnostics && targetType !== unknownType) { let widenedType = getWidenedType(exprType); - if (!(isTypeAssignableTo(targetType, widenedType))) { + + // Permit 'number[] | "foo"' to be asserted to 'string'. + const bothAreStringLike = + someConstituentTypeHasKind(targetType, TypeFlags.StringLike) && + someConstituentTypeHasKind(widenedType, TypeFlags.StringLike); + if (!bothAreStringLike && !(isTypeAssignableTo(targetType, widenedType))) { checkTypeAssignableTo(exprType, targetType, node, Diagnostics.Neither_type_0_nor_type_1_is_assignable_to_the_other); } } @@ -10244,6 +10249,10 @@ namespace ts { case SyntaxKind.ExclamationEqualsToken: case SyntaxKind.EqualsEqualsEqualsToken: case SyntaxKind.ExclamationEqualsEqualsToken: + // Permit 'number[] | "foo"' to be asserted to 'string'. + if (someConstituentTypeHasKind(leftType, TypeFlags.StringLike) && someConstituentTypeHasKind(rightType, TypeFlags.StringLike)) { + return booleanType; + } if (!isTypeAssignableTo(leftType, rightType) && !isTypeAssignableTo(rightType, leftType)) { reportOperatorError(); } @@ -12703,6 +12712,7 @@ namespace ts { let hasDuplicateDefaultClause = false; let expressionType = checkExpression(node.expression); + const expressionTypeIsStringLike = someConstituentTypeHasKind(expressionType, TypeFlags.StringLike); forEach(node.caseBlock.clauses, clause => { // Grammar check for duplicate default clauses, skip if we already report duplicate default clause if (clause.kind === SyntaxKind.DefaultClause && !hasDuplicateDefaultClause) { @@ -12723,6 +12733,12 @@ namespace ts { // TypeScript 1.0 spec (April 2014):5.9 // In a 'switch' statement, each 'case' expression must be of a type that is assignable to or from the type of the 'switch' expression. let caseType = checkExpression(caseClause.expression); + + // Permit 'number[] | "foo"' to be asserted to 'string'. + if (expressionTypeIsStringLike && someConstituentTypeHasKind(caseType, TypeFlags.StringLike)) { + return; + } + if (!isTypeAssignableTo(expressionType, caseType)) { // check 'expressionType isAssignableTo caseType' failed, try the reversed check and report errors if it fails checkTypeAssignableTo(caseType, expressionType, caseClause.expression, /*headMessage*/ undefined);