Skip to content

Commit 25829c4

Browse files
Merge pull request #704 from bryceosterhaus/19
2 parents f6a283e + 617536d commit 25829c4

File tree

4 files changed

+162
-0
lines changed

4 files changed

+162
-0
lines changed

projects/eslint-plugin/configs/general.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ const config = {
157157
],
158158
'sort-keys': ['error', 'asc', {caseSensitive: true, natural: true}],
159159
'spaced-comment': ['error', 'always'],
160+
'valid-typeof': 'error',
160161
},
161162
};
162163

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Check for `null` before typeof === 'object' (no-typeof-object)
2+
3+
`typeof null === 'object'` will evaluate to true, which can easily lead to issues in code. It is safest to explicitly check against null before this expression.
4+
5+
## Rule Details
6+
7+
Examples of **incorrect** code for this rule:
8+
9+
```js
10+
typeof someVal === 'object';
11+
```
12+
13+
Examples of **correct** code for this rule:
14+
15+
```js
16+
someVal !== null && typeof someVal === 'object';
17+
```
18+
19+
## See also
20+
21+
- https://github.com/liferay/liferay-frontend-projects/issues/19
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/**
2+
* SPDX-FileCopyrightText: © 2021 Liferay, Inc. <https://liferay.com>
3+
* SPDX-License-Identifier: MIT
4+
*/
5+
6+
const message =
7+
'checking "typeof x === \'object\'" can be falsy if null. Use "x !== null && typeof x === \'object\'"';
8+
9+
module.exports = {
10+
create(context) {
11+
return {
12+
BinaryExpression(node) {
13+
if (
14+
node.left &&
15+
node.left.type === 'UnaryExpression' &&
16+
node.left.operator === 'typeof' &&
17+
node.right &&
18+
node.right.value === 'object'
19+
) {
20+
const variableName = node.left.argument.name;
21+
22+
const logicalLeft =
23+
node.parent &&
24+
node.parent.type === 'LogicalExpression' &&
25+
node.parent.left;
26+
27+
let hasNullCheck = false;
28+
29+
if (logicalLeft) {
30+
let leftSibling;
31+
32+
if (logicalLeft.type === 'BinaryExpression') {
33+
leftSibling = logicalLeft;
34+
}
35+
36+
if (logicalLeft.type === 'LogicalExpression') {
37+
leftSibling =
38+
logicalLeft.right.type === 'BinaryExpression' &&
39+
logicalLeft.right;
40+
}
41+
42+
hasNullCheck =
43+
leftSibling &&
44+
leftSibling.left &&
45+
leftSibling.left.name === variableName &&
46+
leftSibling.operator === '!==' &&
47+
leftSibling.right.value === null;
48+
49+
if (logicalLeft.type === 'UnaryExpression') {
50+
hasNullCheck =
51+
logicalLeft.operator === '!' &&
52+
logicalLeft.argument.name === variableName;
53+
}
54+
}
55+
56+
if (!hasNullCheck) {
57+
context.report({
58+
fix: (fixer) => {
59+
return fixer.insertTextBefore(
60+
node,
61+
`${variableName} !== null && `
62+
);
63+
},
64+
message,
65+
node,
66+
});
67+
}
68+
}
69+
},
70+
};
71+
},
72+
73+
meta: {
74+
docs: {
75+
category: 'Best Practices',
76+
description: message,
77+
recommended: false,
78+
url:
79+
'https://github.com/liferay/liferay-frontend-projects/issues/19',
80+
},
81+
fixable: true,
82+
schema: [],
83+
type: 'problem',
84+
},
85+
};
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/**
2+
* SPDX-FileCopyrightText: © 2017 Liferay, Inc. <https://liferay.com>
3+
* SPDX-License-Identifier: MIT
4+
*/
5+
6+
const MultiTester = require('../../../../../scripts/MultiTester');
7+
const rule = require('../../../lib/rules/no-typeof-object');
8+
9+
const parserOptions = {
10+
parserOptions: {
11+
ecmaVersion: 6,
12+
sourceType: 'module',
13+
},
14+
};
15+
16+
const ruleTester = new MultiTester(parserOptions);
17+
18+
ruleTester.run('no-typeof-object', rule, {
19+
invalid: [
20+
{
21+
code: `
22+
typeof x === 'object';
23+
24+
someVal && typeof x === 'object';
25+
`,
26+
errors: [
27+
{
28+
message:
29+
'checking "typeof x === \'object\'" can be falsy if null. Use "x !== null && typeof x === \'object\'"',
30+
type: 'BinaryExpression',
31+
},
32+
{
33+
message:
34+
'checking "typeof x === \'object\'" can be falsy if null. Use "x !== null && typeof x === \'object\'"',
35+
type: 'BinaryExpression',
36+
},
37+
],
38+
output: `
39+
x !== null && typeof x === 'object';
40+
41+
someVal && x !== null && typeof x === 'object';
42+
`,
43+
},
44+
],
45+
46+
valid: [
47+
{
48+
code: `
49+
!x && typeof x === 'object';
50+
51+
x !== null && typeof x === 'object';
52+
`,
53+
},
54+
],
55+
});

0 commit comments

Comments
 (0)