diff --git a/packages/eslint-plugin/docs/rules/restrict-template-expressions.md b/packages/eslint-plugin/docs/rules/restrict-template-expressions.md index 0ee7427ddac1..e567b6571b66 100644 --- a/packages/eslint-plugin/docs/rules/restrict-template-expressions.md +++ b/packages/eslint-plugin/docs/rules/restrict-template-expressions.md @@ -35,6 +35,8 @@ type Options = { allowAny?: boolean; // if true, also allow null and undefined in template expressions allowNullish?: boolean; + // if true, also allow RegExp in template expressions + allowRegExp?: boolean; }; const defaults = { @@ -42,6 +44,7 @@ const defaults = { allowBoolean: false, allowAny: false, allowNullish: false, + allowRegExp: false, }; ``` @@ -83,3 +86,17 @@ Examples of additional **correct** code for this rule with `{ allowNullish: true const arg = condition ? 'ok' : null; const msg1 = `arg = ${arg}`; ``` + +### `allowRegExp` + +Examples of additional **correct** code for this rule with `{ allowRegExp: true }`: + +```ts +const arg = new RegExp('foo'); +const msg1 = `arg = ${arg}`; +``` + +```ts +const arg = /foo/; +const msg1 = `arg = ${arg}`; +``` diff --git a/packages/eslint-plugin/src/rules/restrict-template-expressions.ts b/packages/eslint-plugin/src/rules/restrict-template-expressions.ts index a4756266ffca..b20bd5c62bc2 100644 --- a/packages/eslint-plugin/src/rules/restrict-template-expressions.ts +++ b/packages/eslint-plugin/src/rules/restrict-template-expressions.ts @@ -11,6 +11,7 @@ type Options = [ allowBoolean?: boolean; allowAny?: boolean; allowNullish?: boolean; + allowRegExp?: boolean; }, ]; @@ -37,6 +38,7 @@ export default util.createRule({ allowBoolean: { type: 'boolean' }, allowAny: { type: 'boolean' }, allowNullish: { type: 'boolean' }, + allowRegExp: { type: 'boolean' }, }, }, ], @@ -76,6 +78,13 @@ export default util.createRule({ return true; } + if ( + options.allowRegExp && + util.getTypeName(typeChecker, type) === 'RegExp' + ) { + return true; + } + if ( options.allowNullish && util.isTypeFlagSet(type, ts.TypeFlags.Null | ts.TypeFlags.Undefined) diff --git a/packages/eslint-plugin/tests/rules/restrict-template-expressions.test.ts b/packages/eslint-plugin/tests/rules/restrict-template-expressions.test.ts index df5d5aefb259..fea8b82501ae 100644 --- a/packages/eslint-plugin/tests/rules/restrict-template-expressions.test.ts +++ b/packages/eslint-plugin/tests/rules/restrict-template-expressions.test.ts @@ -189,11 +189,56 @@ ruleTester.run('restrict-template-expressions', rule, { } `, }, + // allowRegExp + { + options: [{ allowRegExp: true }], + code: ` + const arg = new RegExp('foo'); + const msg = \`arg = \${arg}\`; + `, + }, + { + options: [{ allowRegExp: true }], + code: ` + const arg = /foo/; + const msg = \`arg = \${arg}\`; + `, + }, + { + options: [{ allowRegExp: true }], + code: ` + declare const arg: string | RegExp; + const msg = \`arg = \${arg}\`; + `, + }, + { + options: [{ allowRegExp: true }], + code: ` + function test(arg: T) { + return \`arg = \${arg}\`; + } + `, + }, + { + options: [{ allowRegExp: true }], + code: ` + function test(arg: T) { + return \`arg = \${arg}\`; + } + `, + }, // allow ALL { - options: [{ allowNumber: true, allowBoolean: true, allowNullish: true }], + options: [ + { + allowNumber: true, + allowBoolean: true, + allowNullish: true, + allowRegExp: true, + }, + ], code: ` - type All = string | number | boolean | null | undefined; + type All = string | number | boolean | null | undefined | RegExp; function test(arg: T) { return \`arg = \${arg}\`; } @@ -338,6 +383,36 @@ ruleTester.run('restrict-template-expressions', rule, { }, ], }, + { + options: [{ allowRegExp: false }], + code: ` + const arg = new RegExp('foo'); + const msg = \`arg = \${arg}\`; + `, + errors: [ + { + messageId: 'invalidType', + data: { type: 'RegExp' }, + line: 3, + column: 30, + }, + ], + }, + { + options: [{ allowRegExp: false }], + code: ` + const arg = /foo/; + const msg = \`arg = \${arg}\`; + `, + errors: [ + { + messageId: 'invalidType', + data: { type: 'RegExp' }, + line: 3, + column: 30, + }, + ], + }, // TS 3.9 change { options: [{ allowAny: true }],