question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Restrict template literal interpolation expressions to strings

See original GitHub issue

Search Terms

“template literal”

There are many hits, some which seem related, but everything I could find was a much bigger ask or wider in scope

Suggestion

Add a compiler option to enforce using only strings in ES6 string template literals

Use Cases

When using string literals, any variables are coerced to strings, which can lead to undesirable behavior.

As far as I can tell there’s no way to avoid this behaviour. In the spirit of tying everything, I’d prefer that only actual string types are permissible for use in string templates to avoid accidental coercion by passing null, undefined or object types that may have unexpected string representations, and force users to explicitly convert them to strings.

Examples

For example:

function formatName(name: string | null): string {
   return `Name is: ${name}`;
} 

formatName(null)  === "Name is: null"

Ideally the compiler would fail since name can be null.

Checklist

My suggestion meets these guidelines:

  • This wouldn’t be a breaking change in existing TypeScript/JavaScript code
  • This wouldn’t change the runtime behavior of existing JavaScript code
  • This could be implemented without emitting different JS based on the types of the expressions
  • This isn’t a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • This feature would agree with the rest of TypeScript’s Design Goals.

Issue Analytics

  • State:open
  • Created 5 years ago
  • Reactions:51
  • Comments:36 (3 by maintainers)

github_iconTop GitHub Comments

14reactions
jamietrecommented, Sep 30, 2020

This is a contrived example; obviously I wouldn’t write a function like this. In real work, we deal with complex data structures that have many fields of differing types. We process data that is far removed from its type definitions. That’s the whole point of static typing.

I wouldn’t write a function so narrowly purposed that allowed null, of course, but I might have a React component that takes a lot of props, some of which can be null or are optional, but I will still eventually use string templates to format data involving those fields. Unless I wrapped every single usage of a string template literal in a function that took a string arg for every field, I would face this risk.

The point of type safety is to protect you from mistakes. If people always correctly grokked the type of every variable they used in practice, then we wouldn’t need typescript at all. But people don’t. I might have a structure:

type Person = {
   firstName: string;
   lastName: string;
   middleName?: string; 
   address: Address;
}

If I did this:

const info = `${data.firstName} ${data.middleName} ${data.lastName} lives at ${data.address}`

I get

“Joe undefined Blow lives at [Object object]”

This would be a very easy mistake to make.

Personally, there’s never a time when I want type coercion. I don’t see why this is a place you’d want it, any more than you’d want it when assigning anything else to a variable of type string. String literal templates only deal with strings; it seems well within the purpose of TypeScript to enforce that we can only pass them strings.

BTW, the use case that this came up had to do with refactoring. I had to take an existing type and change it from string to string | null. If string template literal types were typesafe, the compiler would immediately fail in every place it was used in a string literal, as it currently would fail everywhere else it was no longer safe to use. Without the ability to type string template literals, you can’t ever safely refactor code involving them when widening types.

10reactions
ark120202commented, Feb 10, 2020

typescript-eslint has a restrict-template-expressions rule to catch this

Read more comments on GitHub >

github_iconTop Results From Across the Web

Template literals (Template strings) - JavaScript | MDN
Template literals are literals delimited with backtick ( ` ) characters, allowing for multi-line strings, string interpolation with embedded ...
Read more >
restrict-template-expressions - typescript-eslint
This rule reports on values used in a template literal string that aren't primitives and don't define a more useful .toString() method. .eslintrc.cjs....
Read more >
Documentation - Template Literal Types - TypeScript
Template literal types build on string literal types, and have the ability to expand into many strings via unions. They have the same...
Read more >
Template Strings ES6 prevent line breaks - javascript
var string = `As all string substitutions in Template Strings are JavaScript expressions, we can substitute a lot more than variable names. For...
Read more >
8. Template literals - Exploring JS
A template literal is a new kind of string literal that can span multiple lines and interpolate expressions (include their results). For example:...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found