Skip to content

Commit

Permalink
feat(eslint-plugin): add allowNever support to restrict-template-expr…
Browse files Browse the repository at this point in the history
…essions (#6554)

* feat(eslint-plugin): add allowNever support to restrict-template-expressions

* Update tests

* Fix lint issues

* Fix test
  • Loading branch information
domdomegg committed Mar 19, 2023
1 parent 312225f commit 423f164
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 1 deletion.
Expand Up @@ -90,6 +90,15 @@ const arg = /foo/;
const msg1 = `arg = ${arg}`;
```

### `allowNever`

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

```ts
const arg = 'something';
const msg1 = typeof arg === 'string' ? arg : `arg = ${arg}`;
```

## Related To

- [`no-base-to-string`](./no-base-to-string.md)
Expand Down
10 changes: 10 additions & 0 deletions packages/eslint-plugin/src/rules/restrict-template-expressions.ts
Expand Up @@ -11,6 +11,7 @@ type Options = [
allowAny?: boolean;
allowNullish?: boolean;
allowRegExp?: boolean;
allowNever?: boolean;
},
];

Expand Down Expand Up @@ -58,6 +59,11 @@ export default util.createRule<Options, MessageId>({
'Whether to allow `regexp` typed values in template expressions.',
type: 'boolean',
},
allowNever: {
description:
'Whether to allow `never` typed values in template expressions.',
type: 'boolean',
},
},
},
],
Expand Down Expand Up @@ -111,6 +117,10 @@ export default util.createRule<Options, MessageId>({
return true;
}

if (options.allowNever && util.isTypeNeverType(type)) {
return true;
}

return false;
}

Expand Down
Expand Up @@ -227,6 +227,50 @@ ruleTester.run('restrict-template-expressions', rule, {
}
`,
},
// allowNever
{
options: [{ allowNever: true }],
code: `
declare const value: never;
const stringy = \`\${value}\`;
`,
},
{
options: [{ allowNever: true }],
code: `
const arg = 'hello';
const msg = typeof arg === 'string' ? arg : \`arg = \${arg}\`;
`,
},
{
options: [{ allowNever: true }],
code: `
function test(arg: 'one' | 'two') {
switch (arg) {
case 'one':
return 1;
case 'two':
return 2;
default:
throw new Error(\`Unrecognised arg: \${arg}\`);
}
}
`,
},
{
options: [{ allowNever: true }],
code: `
// more variants may be added to Foo in the future
type Foo = { type: 'a'; value: number };
function checkFoosAreMatching(foo1: Foo, foo2: Foo) {
if (foo1.type !== foo2.type) {
// since Foo currently only has one variant, this code is never run, and \`foo1.type\` has type \`never\`.
throw new Error(\`expected \${foo1.type}, found \${foo2.type}\`);
}
}
`,
},
// allow ALL
{
options: [
Expand All @@ -235,10 +279,11 @@ ruleTester.run('restrict-template-expressions', rule, {
allowBoolean: true,
allowNullish: true,
allowRegExp: true,
allowNever: true,
},
],
code: `
type All = string | number | boolean | null | undefined | RegExp;
type All = string | number | boolean | null | undefined | RegExp | never;
function test<T extends All>(arg: T) {
return \`arg = \${arg}\`;
}
Expand Down Expand Up @@ -418,6 +463,21 @@ ruleTester.run('restrict-template-expressions', rule, {
},
],
},
{
options: [{ allowNever: false }],
code: `
declare const value: never;
const stringy = \`\${value}\`;
`,
errors: [
{
messageId: 'invalidType',
data: { type: 'never' },
line: 3,
column: 28,
},
],
},
// TS 3.9 change
{
options: [{ allowAny: true }],
Expand Down

0 comments on commit 423f164

Please sign in to comment.