diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index dfa8c72d36645..44a3241045cc4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -32810,7 +32810,7 @@ namespace ts { case SyntaxKind.MinusToken: case SyntaxKind.TildeToken: checkNonNullType(operandType, node.operand); - if (maybeTypeOfKind(operandType, TypeFlags.ESSymbolLike)) { + if (maybeTypeOfKindConsideringBaseConstraint(operandType, TypeFlags.ESSymbolLike)) { error(node.operand, Diagnostics.The_0_operator_cannot_be_applied_to_type_symbol, tokenToString(node.operator)); } if (node.operator === SyntaxKind.PlusToken) { @@ -32871,6 +32871,15 @@ namespace ts { return numberType; } + function maybeTypeOfKindConsideringBaseConstraint(type: Type, kind: TypeFlags): boolean { + if (maybeTypeOfKind(type, kind)) { + return true; + } + + const baseConstraint = getBaseConstraintOrType(type); + return !!baseConstraint && maybeTypeOfKind(baseConstraint, kind); + } + // Return true if type might be of the given kind. A union or intersection type might be of a given // kind if at least one constituent type is of the given kind. function maybeTypeOfKind(type: Type, kind: TypeFlags): boolean { @@ -33654,8 +33663,8 @@ namespace ts { // Return true if there was no error, false if there was an error. function checkForDisallowedESSymbolOperand(operator: SyntaxKind): boolean { const offendingSymbolOperand = - maybeTypeOfKind(leftType, TypeFlags.ESSymbolLike) ? left : - maybeTypeOfKind(rightType, TypeFlags.ESSymbolLike) ? right : + maybeTypeOfKindConsideringBaseConstraint(leftType, TypeFlags.ESSymbolLike) ? left : + maybeTypeOfKindConsideringBaseConstraint(rightType, TypeFlags.ESSymbolLike) ? right : undefined; if (offendingSymbolOperand) { @@ -33893,7 +33902,7 @@ namespace ts { const types = []; for (const span of node.templateSpans) { const type = checkExpression(span.expression); - if (maybeTypeOfKind(type, TypeFlags.ESSymbolLike)) { + if (maybeTypeOfKindConsideringBaseConstraint(type, TypeFlags.ESSymbolLike)) { error(span.expression, Diagnostics.Implicit_conversion_of_a_symbol_to_a_string_will_fail_at_runtime_Consider_wrapping_this_expression_in_String); } texts.push(span.literal.text); diff --git a/tests/baselines/reference/noImplicitSymbolToString.errors.txt b/tests/baselines/reference/noImplicitSymbolToString.errors.txt index cb664d9a8b93e..b90cf982dd398 100644 --- a/tests/baselines/reference/noImplicitSymbolToString.errors.txt +++ b/tests/baselines/reference/noImplicitSymbolToString.errors.txt @@ -3,9 +3,19 @@ tests/cases/compiler/noImplicitSymbolToString.ts(7,30): error TS2469: The '+' op tests/cases/compiler/noImplicitSymbolToString.ts(8,8): error TS2469: The '+=' operator cannot be applied to type 'symbol'. tests/cases/compiler/noImplicitSymbolToString.ts(13,47): error TS2731: Implicit conversion of a 'symbol' to a 'string' will fail at runtime. Consider wrapping this expression in 'String(...)'. tests/cases/compiler/noImplicitSymbolToString.ts(13,90): error TS2731: Implicit conversion of a 'symbol' to a 'string' will fail at runtime. Consider wrapping this expression in 'String(...)'. +tests/cases/compiler/noImplicitSymbolToString.ts(21,15): error TS2731: Implicit conversion of a 'symbol' to a 'string' will fail at runtime. Consider wrapping this expression in 'String(...)'. +tests/cases/compiler/noImplicitSymbolToString.ts(26,8): error TS2731: Implicit conversion of a 'symbol' to a 'string' will fail at runtime. Consider wrapping this expression in 'String(...)'. +tests/cases/compiler/noImplicitSymbolToString.ts(27,5): error TS2469: The '+' operator cannot be applied to type 'symbol'. +tests/cases/compiler/noImplicitSymbolToString.ts(28,6): error TS2469: The '+' operator cannot be applied to type 'symbol'. +tests/cases/compiler/noImplicitSymbolToString.ts(31,8): error TS2731: Implicit conversion of a 'symbol' to a 'string' will fail at runtime. Consider wrapping this expression in 'String(...)'. +tests/cases/compiler/noImplicitSymbolToString.ts(32,5): error TS2469: The '+' operator cannot be applied to type 'symbol'. +tests/cases/compiler/noImplicitSymbolToString.ts(33,6): error TS2469: The '+' operator cannot be applied to type 'symbol'. +tests/cases/compiler/noImplicitSymbolToString.ts(43,8): error TS2731: Implicit conversion of a 'symbol' to a 'string' will fail at runtime. Consider wrapping this expression in 'String(...)'. +tests/cases/compiler/noImplicitSymbolToString.ts(44,5): error TS2469: The '+' operator cannot be applied to type 'symbol'. +tests/cases/compiler/noImplicitSymbolToString.ts(45,6): error TS2469: The '+' operator cannot be applied to type 'symbol'. -==== tests/cases/compiler/noImplicitSymbolToString.ts (5 errors) ==== +==== tests/cases/compiler/noImplicitSymbolToString.ts (15 errors) ==== // Fix #19666 let symbol!: symbol; @@ -29,4 +39,57 @@ tests/cases/compiler/noImplicitSymbolToString.ts(13,90): error TS2731: Implicit !!! error TS2731: Implicit conversion of a 'symbol' to a 'string' will fail at runtime. Consider wrapping this expression in 'String(...)'. ~~~~~~~~~~~~~~~~~ !!! error TS2731: Implicit conversion of a 'symbol' to a 'string' will fail at runtime. Consider wrapping this expression in 'String(...)'. + + + // Fix #44462 + + type StringOrSymbol = string | symbol; + + function getKey(key: S) { + return `${key} is the key`; + ~~~ +!!! error TS2731: Implicit conversion of a 'symbol' to a 'string' will fail at runtime. Consider wrapping this expression in 'String(...)'. + } + + function getKey1(key: S) { + let s1!: S; + `${s1}`; + ~~ +!!! error TS2731: Implicit conversion of a 'symbol' to a 'string' will fail at runtime. Consider wrapping this expression in 'String(...)'. + s1 + ''; + ~~ +!!! error TS2469: The '+' operator cannot be applied to type 'symbol'. + +s1; + ~~ +!!! error TS2469: The '+' operator cannot be applied to type 'symbol'. + + let s2!: S | string; + `${s2}`; + ~~ +!!! error TS2731: Implicit conversion of a 'symbol' to a 'string' will fail at runtime. Consider wrapping this expression in 'String(...)'. + s2 + ''; + ~~ +!!! error TS2469: The '+' operator cannot be applied to type 'symbol'. + +s2; + ~~ +!!! error TS2469: The '+' operator cannot be applied to type 'symbol'. + } + + function getKey2(key: S) { + let s1!: S; + `${s1}`; + s1 + ''; + +s1; + + let s2!: S | symbol; + `${s2}`; + ~~ +!!! error TS2731: Implicit conversion of a 'symbol' to a 'string' will fail at runtime. Consider wrapping this expression in 'String(...)'. + s2 + ''; + ~~ +!!! error TS2469: The '+' operator cannot be applied to type 'symbol'. + +s2; + ~~ +!!! error TS2469: The '+' operator cannot be applied to type 'symbol'. + } \ No newline at end of file diff --git a/tests/baselines/reference/noImplicitSymbolToString.js b/tests/baselines/reference/noImplicitSymbolToString.js index fed276b8a731e..68f581faa3924 100644 --- a/tests/baselines/reference/noImplicitSymbolToString.js +++ b/tests/baselines/reference/noImplicitSymbolToString.js @@ -12,6 +12,39 @@ let symbolUnionNumber!: symbol | number; let symbolUnionString!: symbol | string; const templateStrUnion = `union with number ${symbolUnionNumber} and union with string ${symbolUnionString}`; + + +// Fix #44462 + +type StringOrSymbol = string | symbol; + +function getKey(key: S) { + return `${key} is the key`; +} + +function getKey1(key: S) { + let s1!: S; + `${s1}`; + s1 + ''; + +s1; + + let s2!: S | string; + `${s2}`; + s2 + ''; + +s2; +} + +function getKey2(key: S) { + let s1!: S; + `${s1}`; + s1 + ''; + +s1; + + let s2!: S | symbol; + `${s2}`; + s2 + ''; + +s2; +} //// [noImplicitSymbolToString.js] @@ -24,3 +57,26 @@ str += symbol; var symbolUnionNumber; var symbolUnionString; var templateStrUnion = "union with number ".concat(symbolUnionNumber, " and union with string ").concat(symbolUnionString); +function getKey(key) { + return "".concat(key, " is the key"); +} +function getKey1(key) { + var s1; + "".concat(s1); + s1 + ''; + +s1; + var s2; + "".concat(s2); + s2 + ''; + +s2; +} +function getKey2(key) { + var s1; + "".concat(s1); + s1 + ''; + +s1; + var s2; + "".concat(s2); + s2 + ''; + +s2; +} diff --git a/tests/baselines/reference/noImplicitSymbolToString.symbols b/tests/baselines/reference/noImplicitSymbolToString.symbols index b2a08e151ab64..4922e1a112c99 100644 --- a/tests/baselines/reference/noImplicitSymbolToString.symbols +++ b/tests/baselines/reference/noImplicitSymbolToString.symbols @@ -30,3 +30,86 @@ const templateStrUnion = `union with number ${symbolUnionNumber} and union with >symbolUnionNumber : Symbol(symbolUnionNumber, Decl(noImplicitSymbolToString.ts, 9, 3)) >symbolUnionString : Symbol(symbolUnionString, Decl(noImplicitSymbolToString.ts, 10, 3)) + +// Fix #44462 + +type StringOrSymbol = string | symbol; +>StringOrSymbol : Symbol(StringOrSymbol, Decl(noImplicitSymbolToString.ts, 12, 109)) + +function getKey(key: S) { +>getKey : Symbol(getKey, Decl(noImplicitSymbolToString.ts, 17, 38)) +>S : Symbol(S, Decl(noImplicitSymbolToString.ts, 19, 16)) +>StringOrSymbol : Symbol(StringOrSymbol, Decl(noImplicitSymbolToString.ts, 12, 109)) +>key : Symbol(key, Decl(noImplicitSymbolToString.ts, 19, 42)) +>S : Symbol(S, Decl(noImplicitSymbolToString.ts, 19, 16)) + + return `${key} is the key`; +>key : Symbol(key, Decl(noImplicitSymbolToString.ts, 19, 42)) +} + +function getKey1(key: S) { +>getKey1 : Symbol(getKey1, Decl(noImplicitSymbolToString.ts, 21, 1)) +>S : Symbol(S, Decl(noImplicitSymbolToString.ts, 23, 17)) +>key : Symbol(key, Decl(noImplicitSymbolToString.ts, 23, 35)) +>S : Symbol(S, Decl(noImplicitSymbolToString.ts, 23, 17)) + + let s1!: S; +>s1 : Symbol(s1, Decl(noImplicitSymbolToString.ts, 24, 7)) +>S : Symbol(S, Decl(noImplicitSymbolToString.ts, 23, 17)) + + `${s1}`; +>s1 : Symbol(s1, Decl(noImplicitSymbolToString.ts, 24, 7)) + + s1 + ''; +>s1 : Symbol(s1, Decl(noImplicitSymbolToString.ts, 24, 7)) + + +s1; +>s1 : Symbol(s1, Decl(noImplicitSymbolToString.ts, 24, 7)) + + let s2!: S | string; +>s2 : Symbol(s2, Decl(noImplicitSymbolToString.ts, 29, 7)) +>S : Symbol(S, Decl(noImplicitSymbolToString.ts, 23, 17)) + + `${s2}`; +>s2 : Symbol(s2, Decl(noImplicitSymbolToString.ts, 29, 7)) + + s2 + ''; +>s2 : Symbol(s2, Decl(noImplicitSymbolToString.ts, 29, 7)) + + +s2; +>s2 : Symbol(s2, Decl(noImplicitSymbolToString.ts, 29, 7)) +} + +function getKey2(key: S) { +>getKey2 : Symbol(getKey2, Decl(noImplicitSymbolToString.ts, 33, 1)) +>S : Symbol(S, Decl(noImplicitSymbolToString.ts, 35, 17)) +>key : Symbol(key, Decl(noImplicitSymbolToString.ts, 35, 35)) +>S : Symbol(S, Decl(noImplicitSymbolToString.ts, 35, 17)) + + let s1!: S; +>s1 : Symbol(s1, Decl(noImplicitSymbolToString.ts, 36, 7)) +>S : Symbol(S, Decl(noImplicitSymbolToString.ts, 35, 17)) + + `${s1}`; +>s1 : Symbol(s1, Decl(noImplicitSymbolToString.ts, 36, 7)) + + s1 + ''; +>s1 : Symbol(s1, Decl(noImplicitSymbolToString.ts, 36, 7)) + + +s1; +>s1 : Symbol(s1, Decl(noImplicitSymbolToString.ts, 36, 7)) + + let s2!: S | symbol; +>s2 : Symbol(s2, Decl(noImplicitSymbolToString.ts, 41, 7)) +>S : Symbol(S, Decl(noImplicitSymbolToString.ts, 35, 17)) + + `${s2}`; +>s2 : Symbol(s2, Decl(noImplicitSymbolToString.ts, 41, 7)) + + s2 + ''; +>s2 : Symbol(s2, Decl(noImplicitSymbolToString.ts, 41, 7)) + + +s2; +>s2 : Symbol(s2, Decl(noImplicitSymbolToString.ts, 41, 7)) +} + diff --git a/tests/baselines/reference/noImplicitSymbolToString.types b/tests/baselines/reference/noImplicitSymbolToString.types index c21c0e07bfded..7111542c4a318 100644 --- a/tests/baselines/reference/noImplicitSymbolToString.types +++ b/tests/baselines/reference/noImplicitSymbolToString.types @@ -36,3 +36,92 @@ const templateStrUnion = `union with number ${symbolUnionNumber} and union with >symbolUnionNumber : number | symbol >symbolUnionString : string | symbol + +// Fix #44462 + +type StringOrSymbol = string | symbol; +>StringOrSymbol : StringOrSymbol + +function getKey(key: S) { +>getKey : (key: S) => string +>key : S + + return `${key} is the key`; +>`${key} is the key` : string +>key : S +} + +function getKey1(key: S) { +>getKey1 : (key: S) => void +>key : S + + let s1!: S; +>s1 : S + + `${s1}`; +>`${s1}` : string +>s1 : S + + s1 + ''; +>s1 + '' : string +>s1 : S +>'' : "" + + +s1; +>+s1 : number +>s1 : S + + let s2!: S | string; +>s2 : string | S + + `${s2}`; +>`${s2}` : string +>s2 : string | S + + s2 + ''; +>s2 + '' : string +>s2 : string | S +>'' : "" + + +s2; +>+s2 : number +>s2 : string | S +} + +function getKey2(key: S) { +>getKey2 : (key: S) => void +>key : S + + let s1!: S; +>s1 : S + + `${s1}`; +>`${s1}` : string +>s1 : S + + s1 + ''; +>s1 + '' : string +>s1 : S +>'' : "" + + +s1; +>+s1 : number +>s1 : S + + let s2!: S | symbol; +>s2 : symbol | S + + `${s2}`; +>`${s2}` : string +>s2 : symbol | S + + s2 + ''; +>s2 + '' : string +>s2 : symbol | S +>'' : "" + + +s2; +>+s2 : number +>s2 : symbol | S +} + diff --git a/tests/cases/compiler/noImplicitSymbolToString.ts b/tests/cases/compiler/noImplicitSymbolToString.ts index 16690d6d845cb..a3a797c5f67a8 100644 --- a/tests/cases/compiler/noImplicitSymbolToString.ts +++ b/tests/cases/compiler/noImplicitSymbolToString.ts @@ -11,3 +11,36 @@ let symbolUnionNumber!: symbol | number; let symbolUnionString!: symbol | string; const templateStrUnion = `union with number ${symbolUnionNumber} and union with string ${symbolUnionString}`; + + +// Fix #44462 + +type StringOrSymbol = string | symbol; + +function getKey(key: S) { + return `${key} is the key`; +} + +function getKey1(key: S) { + let s1!: S; + `${s1}`; + s1 + ''; + +s1; + + let s2!: S | string; + `${s2}`; + s2 + ''; + +s2; +} + +function getKey2(key: S) { + let s1!: S; + `${s1}`; + s1 + ''; + +s1; + + let s2!: S | symbol; + `${s2}`; + s2 + ''; + +s2; +} pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy