There is some common pattern
const barFunc = () => 'World';
const fooStr = `Hello, ${barFunc()}`; // Hello, World
But it's easy to miss brackets around function and this would be not an error
const barFunc = () => 'World';
const fooStr = `Hello, ${barFunc}`; // "Hello, () => 'World'"
What does your suggested rule do?
If it's on, require explicit toString or String call around function
Like this
// yeah, we really want function source code here
const barFunc = () => 'World';
const fooStr = `Hello, ${String(barFunc)}`; // "Hello, () => 'World'"
Additional context
What about spreading this rule for other data types?
I think this is frustrating sometimes:
const name = { foo: 'Foo' };
alert('Hello, ' + name); // Hello, [object Object] (╯°□°)╯︵ ┻━┻
What do you think?
@ColCh this is a really interesting idea, thanks! I've definitely felt the exact pain you've described, and would like to see a rule helping.
On the other hand, the following should be allowed, right?
class CanBeStringified {
toString() {
return "This works fine...";
}
}
const stringified = new CanBeStringified();
alert(`Result: ${stringified}`);
So is it that this rule should ban objects that whose toString is "reasonable"? Meaning: primitives and objects/instances with their own toString are fine, but regular methods and functions aren't? What about arrays, unknowns, anys, and type unions or intersections?
Let's discuss a bit to nail down how this should behave.
I was just looking for a rule for this. https://github.com/Microsoft/vscode/issues/68966
Meaning: primitives and objects/instances with their own
toStringare fine, but regular methods and functions aren't? What about arrays,unknowns,anys, and type unions or intersections?
Yes, I would want something specifically for functions and methods, (or type unions that could represent functions). I think that's the mistake that I'm most likely to make. It could also be useful for arrays, objects that don't have a non-default toString method, unknown etc.
Since TSLint migration to ESLint (medium post) and presence of this rule in eslint (no-implicit-coercion), I think it would be nice just to close this issue :) What do you think?
@ColCh there are still very many users on TSLint who rely on the features and/or rules that haven't yet been ported over to ESLint. Let's keep this issue open for the time being.
no-implicit-coercion also doesn't quite capture what this rule is proposed to do. Knowing whether something is a function requires type info, so it looks like that rule is a "weaker" form of this one.
Let's call this strict-string-expressions, to mirror strict-boolean-expressions
@JoshuaKGoldberg https://github.com/palantir/tslint/issues/4512#issuecomment-462049970 That makes things complicated :)
What about this example?
class Greeter {
constructor(
private name: string
) { }
getGreetMsg() {
return `Hello, ${this.name}!`;
}
toString() {
return `Greeter for ${this.name}`;
}
}
const greeter = new Greeter("World");
alert(`Result: ${greeter}`); // linter -> ERR or OK ?
I think, that in this case .toString() should be called too, like
alert(`Result: ${greeter.toString()}`); // linter -> OK
What about arrays, unknowns, anys, and type unions or intersections
hm, may be all things would require explicit String call but not string's
like
alert('test' + new Greeter()); // ERR
alert('test' + NeverTypeVar); // ERR
alert('test' + []); // ERR
alert('test' + { foo: 'foo' }); // ERR
// e.g. if x not typeof 'string', return ERR status
and pass only for strings
alert('test' + 'FOO'); // OK!
@ColCh yes, that makes sense & I agree. The simplest theology here makes sense: complex objects such as class instances and functions should have explicit .toString()s. 👍
Note: per #4534, this issue will be closed in less than a month if no PR is sent to add the rule. If you _really_ need the rule, custom rules are always an option and can be maintained outside this repo!
Most helpful comment
I was just looking for a rule for this. https://github.com/Microsoft/vscode/issues/68966
Yes, I would want something specifically for functions and methods, (or type unions that could represent functions). I think that's the mistake that I'm most likely to make. It could also be useful for arrays, objects that don't have a non-default toString method,
unknownetc.