Skip to content

Commit 3f305b1

Browse files
bradzacherJamesHenry
authored andcommitted
fix(eslint-plugin): restrict-plus-operands: generic constraint support (#440)
1 parent 92e65ec commit 3f305b1

File tree

2 files changed

+89
-3
lines changed

2 files changed

+89
-3
lines changed

Diff for: packages/eslint-plugin/src/rules/restrict-plus-operands.ts

+11-3
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ export default util.createRule({
99
docs: {
1010
description:
1111
'When adding two variables, operands must both be of type number or of type string.',
12-
tslintRuleName: 'restrict-plus-operands',
12+
tslintName: 'restrict-plus-operands',
1313
category: 'Best Practices',
1414
recommended: false,
1515
},
@@ -32,10 +32,18 @@ export default util.createRule({
3232

3333
/**
3434
* Helper function to get base type of node
35-
* @param type type to be evaluated
36-
* @returns string, number or invalid
3735
*/
3836
function getBaseTypeOfLiteralType(type: ts.Type): BaseLiteral {
37+
const constraint = type.getConstraint();
38+
if (
39+
constraint &&
40+
// for generic types with union constraints, it will return itself from getConstraint
41+
// so we have to guard against infinite recursion...
42+
constraint !== type
43+
) {
44+
return getBaseTypeOfLiteralType(constraint);
45+
}
46+
3947
if (type.isNumberLiteral()) {
4048
return 'number';
4149
}

Diff for: packages/eslint-plugin/tests/rules/restrict-plus-operands.test.ts

+78
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,27 @@ var foo = ("5.5" as string) + pair.second;
6060
`const foo = 'hello' + (someBoolean ? 'a' : 'b') + (() => someBoolean ? 'c' : 'd')() + 'e';`,
6161
`const balls = true;`,
6262
`balls === true;`,
63+
// https://github.com/typescript-eslint/typescript-eslint/issues/230
64+
`
65+
function foo<T extends string>(a: T) {
66+
return a + "";
67+
}
68+
`,
69+
`
70+
function foo<T extends "a" | "b">(a: T) {
71+
return a + "";
72+
}
73+
`,
74+
`
75+
function foo<T extends number>(a: T) {
76+
return a + 1;
77+
}
78+
`,
79+
`
80+
function foo<T extends 1>(a: T) {
81+
return a + 1;
82+
}
83+
`,
6384
],
6485
invalid: [
6586
{
@@ -305,5 +326,62 @@ var foo = pair + pair;
305326
},
306327
],
307328
},
329+
// https://github.com/typescript-eslint/typescript-eslint/issues/230
330+
{
331+
code: `
332+
function foo<T extends string>(a: T) {
333+
return a + 1;
334+
}
335+
`,
336+
errors: [
337+
{
338+
messageId: 'notStrings',
339+
line: 3,
340+
column: 12,
341+
},
342+
],
343+
},
344+
{
345+
code: `
346+
function foo<T extends "a" | "b">(a: T) {
347+
return a + 1;
348+
}
349+
`,
350+
errors: [
351+
{
352+
messageId: 'notStrings',
353+
line: 3,
354+
column: 12,
355+
},
356+
],
357+
},
358+
{
359+
code: `
360+
function foo<T extends number>(a: T) {
361+
return a + "";
362+
}
363+
`,
364+
errors: [
365+
{
366+
messageId: 'notStrings',
367+
line: 3,
368+
column: 12,
369+
},
370+
],
371+
},
372+
{
373+
code: `
374+
function foo<T extends 1>(a: T) {
375+
return a + "";
376+
}
377+
`,
378+
errors: [
379+
{
380+
messageId: 'notStrings',
381+
line: 3,
382+
column: 12,
383+
},
384+
],
385+
},
308386
],
309387
});

0 commit comments

Comments
 (0)