Transform ID:Documentation Index
Fetch the complete documentation index at: https://docs.refactron.dev/llms.txt
Use this file to discover all available pages before exploring further.
string_concat_to_template_literal
Language: TypeScript
What it does
Rewrites+-based string concatenations to template literals. Both left-leaning and right-leaning trees flatten to the same operand list, so "a" + b + "c" and "a" + (b + "c") both become `a${b}c`. Backticks (`) and literal ${ digraphs in the source are faithfully escaped so the resulting template parses identically.
Type safety is enforced via ts-morph’s getType() on every non-string-literal operand: only string / number / boolean (and unions of those) are allowed. Anything any, unknown, or non-primitive refuses cleanly — we never paper over an accidental + (addition) that happens to involve a string somewhere. Transform at src/transform/transforms/typescript/string-concat-to-template-literal.ts.
Detector pattern
The detector atsrc/analyze/detectors/typescript/string-concat.ts flags top-level +-binary chains (the outermost + in a sequence of nested +-binaries) where at least one operand is a string literal.
Preconditions
non_es2015— refuses when the resolved tsconfigtargetpredates ES2015. Template literals aren’t in the runtime grammar before ES2015.unknown_operand_type— refuses when any operand has typeanyorunknown. Could be addition, could be concatenation — we don’t guess.non_coercible_operand— refuses when any operand has a non-primitive type (object, array, …). Coercing via implicittoString()is rarely intentional.- At least one operand in the chain is a string literal (
"…"or`…`no-substitution template). Pure-numerica + b + cis left alone.
Before / after
Edge cases NOT handled (skip via precondition)
any/unknownoperands —unknown_operand_type. The+could be addition.- Non-primitive operands (objects, arrays, custom classes) —
non_coercible_operand.toString()coercion is almost never intended. - tsconfig
target< ES2015 —non_es2015; template literals aren’t available. - Pure-numeric chains with no string operand — not a concatenation; left alone.
- A
+-chain at a sub-expression position whose parent is also a+-binary — only the outermost chain is rewritten (the inner one flattens into its operand list).
The type checks are intentionally conservative: a chain with even one untyped operand refuses outright. This costs a few legitimate rewrites in untyped code, but eliminates the risk of converting an arithmetic
+ into a string-coercion bug.