Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(eslint-plugin): [no-base-to-string] add option to ignore tagged templates #1763

26 changes: 26 additions & 0 deletions packages/eslint-plugin/docs/rules/no-base-to-string.md
Expand Up @@ -52,6 +52,32 @@ const literalWithToString = {
`Value: ${literalWithToString}`;
```

## Options

The rule accepts an options object with the following properties:

```ts
type Options = {
// if true, interpolated expressions in tagged templates will not be checked
ignoreTaggedTemplateExpressions?: boolean;
};

const defaults = {
ignoreTaggedTemplateExpressions: false,
};
```

### `ignoreTaggedTemplateExpressions`

This allows to skip checking tagged templates, for cases where the tags do not necessarily stringify interpolated values.

Examples of additional **correct** code for this rule with `{ ignoreTaggedTemplateExpressions: true }`:

```ts
function tag() {}
tag`${{}}`;
```

## When Not To Use It

If you don't mind `"[object Object]"` in your strings, then you will not need this rule.
Expand Down
34 changes: 29 additions & 5 deletions packages/eslint-plugin/src/rules/no-base-to-string.ts
Expand Up @@ -12,7 +12,14 @@ enum Usefulness {
Sometimes = 'may',
}

export default util.createRule({
type Options = [
{
ignoreTaggedTemplateExpressions?: boolean;
},
];
type MessageIds = 'baseToString';

export default util.createRule<Options, MessageIds>({
name: 'no-base-to-string',
meta: {
docs: {
Expand All @@ -26,11 +33,22 @@ export default util.createRule({
baseToString:
"'{{name}} {{certainty}} evaluate to '[object Object]' when stringified.",
},
schema: [],
schema: [
{
type: 'object',
properties: {
ignoreTaggedTemplateExpressions: {
type: 'boolean',
default: false,
},
},
additionalProperties: false,
},
],
type: 'suggestion',
},
defaultOptions: [],
create(context) {
defaultOptions: [{ ignoreTaggedTemplateExpressions: false }],
create(context, [options]) {
const parserServices = util.getParserServices(context);
const typeChecker = parserServices.program.getTypeChecker();

Expand Down Expand Up @@ -110,8 +128,14 @@ export default util.createRule({
const memberExpr = node.parent as TSESTree.MemberExpression;
checkExpression(memberExpr.object);
},

TemplateLiteral(node: TSESTree.TemplateLiteral): void {
if (
options.ignoreTaggedTemplateExpressions &&
node.parent &&
node.parent.type === AST_NODE_TYPES.TaggedTemplateExpression
) {
return;
}
for (const expression of node.expressions) {
checkExpression(expression);
}
Expand Down
26 changes: 26 additions & 0 deletions packages/eslint-plugin/tests/rules/no-base-to-string.test.ts
Expand Up @@ -70,6 +70,17 @@ const literalWithToString = {
'let _ = {} ^ {};',
'let _ = {} << {};',
'let _ = {} >> {};',
{
code: `
function tag() {}
tag\`\${{}}\`;
`,
options: [
{
ignoreTaggedTemplateExpressions: true,
},
],
},
],
invalid: [
{
Expand All @@ -84,6 +95,21 @@ const literalWithToString = {
},
],
},
{
code: `
function tag() {}
tag\`\${{}}\`;
`,
errors: [
{
data: {
certainty: 'will',
name: '{}',
},
messageId: 'baseToString',
},
],
},
{
code: '({}.toString());',
errors: [
Expand Down