From f5edb9938c33f8b68f026eba00db3abe9359ced3 Mon Sep 17 00:00:00 2001 From: Susisu Date: Mon, 13 Apr 2020 05:29:14 +0900 Subject: [PATCH] feat(eslint-plugin): [no-base-to-string] add option to ignore tagged templates (#1763) --- .../docs/rules/no-base-to-string.md | 26 ++++++++++++++ .../src/rules/no-base-to-string.ts | 34 ++++++++++++++++--- .../tests/rules/no-base-to-string.test.ts | 26 ++++++++++++++ 3 files changed, 81 insertions(+), 5 deletions(-) diff --git a/packages/eslint-plugin/docs/rules/no-base-to-string.md b/packages/eslint-plugin/docs/rules/no-base-to-string.md index 4e73eb6339a..68bd82568b1 100644 --- a/packages/eslint-plugin/docs/rules/no-base-to-string.md +++ b/packages/eslint-plugin/docs/rules/no-base-to-string.md @@ -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. diff --git a/packages/eslint-plugin/src/rules/no-base-to-string.ts b/packages/eslint-plugin/src/rules/no-base-to-string.ts index 98a37c74084..47803f8e2aa 100644 --- a/packages/eslint-plugin/src/rules/no-base-to-string.ts +++ b/packages/eslint-plugin/src/rules/no-base-to-string.ts @@ -12,7 +12,14 @@ enum Usefulness { Sometimes = 'may', } -export default util.createRule({ +type Options = [ + { + ignoreTaggedTemplateExpressions?: boolean; + }, +]; +type MessageIds = 'baseToString'; + +export default util.createRule({ name: 'no-base-to-string', meta: { docs: { @@ -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(); @@ -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); } diff --git a/packages/eslint-plugin/tests/rules/no-base-to-string.test.ts b/packages/eslint-plugin/tests/rules/no-base-to-string.test.ts index cd2e4b166a9..59abfbb1f60 100644 --- a/packages/eslint-plugin/tests/rules/no-base-to-string.test.ts +++ b/packages/eslint-plugin/tests/rules/no-base-to-string.test.ts @@ -70,6 +70,17 @@ const literalWithToString = { 'let _ = {} ^ {};', 'let _ = {} << {};', 'let _ = {} >> {};', + { + code: ` + function tag() {} + tag\`\${{}}\`; + `, + options: [ + { + ignoreTaggedTemplateExpressions: true, + }, + ], + }, ], invalid: [ { @@ -84,6 +95,21 @@ const literalWithToString = { }, ], }, + { + code: ` + function tag() {} + tag\`\${{}}\`; + `, + errors: [ + { + data: { + certainty: 'will', + name: '{}', + }, + messageId: 'baseToString', + }, + ], + }, { code: '({}.toString());', errors: [