Skip to content
This repository has been archived by the owner on Aug 4, 2020. It is now read-only.

Add valid-typeof rule with support for BigInt #161

Merged
merged 1 commit into from
Sep 6, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ original ones as well!).
"babel/object-curly-spacing": 1,
"babel/quotes": 1,
"babel/semi": 1,
"babel/no-unused-expressions": 1
"babel/no-unused-expressions": 1,
"babel/valid-typeof": 1
}
}
```
Expand All @@ -49,6 +50,7 @@ Each rule corresponds to a core `eslint` rule, and has the same options.
- `babel/quotes`: doesn't complain about JSX fragment shorthand syntax (`<>foo</>;`)
- `babel/semi`: doesn't fail when using `for await (let something of {})`. Includes class properties (🛠)
- `babel/no-unused-expressions`: doesn't fail when using `do` expressions or [optional chaining](https://github.com/tc39/proposal-optional-chaining) (`a?.b()`).
- `babel/valid-typeof`: doesn't complain when used with [BigInt](https://github.com/tc39/proposal-bigint) (`typeof BigInt(9007199254740991) === 'bigint'`).

#### Deprecated

Expand Down
12 changes: 12 additions & 0 deletions rules/valid-typeof.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
"use strict";

const ruleComposer = require('eslint-rule-composer');
const eslint = require('eslint');
const validTypeOf = new eslint.Linter().getRules().get('valid-typeof');

module.exports = ruleComposer.filterReports(
validTypeOf,
(problem, metadata) => {
return problem.node.value !== 'bigint';
}
)
193 changes: 193 additions & 0 deletions tests/rules/valid-typeof.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
/**
* @fileoverview Ensures that the results of typeof are compared against a valid string
* @author Ian Christian Myers
ljharb marked this conversation as resolved.
Show resolved Hide resolved
*/

"use strict";

//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------

const rule = require("../../rules/valid-typeof"),
RuleTester = require("../RuleTester");

//------------------------------------------------------------------------------
// Tests
//------------------------------------------------------------------------------

const ruleTester = new RuleTester();

ruleTester.run("valid-typeof", rule, {
valid: [
// Original test cases.
"typeof foo === 'string'",
"typeof foo === 'object'",
"typeof foo === 'function'",
"typeof foo === 'undefined'",
"typeof foo === 'boolean'",
"typeof foo === 'number'",
"'string' === typeof foo",
"'object' === typeof foo",
"'function' === typeof foo",
"'undefined' === typeof foo",
"'boolean' === typeof foo",
"'number' === typeof foo",
"typeof foo === typeof bar",
"typeof foo === baz",
"typeof foo !== someType",
"typeof bar != someType",
"someType === typeof bar",
"someType == typeof bar",
"typeof foo == 'string'",
"typeof(foo) === 'string'",
"typeof(foo) !== 'string'",
"typeof(foo) == 'string'",
"typeof(foo) != 'string'",
"var oddUse = typeof foo + 'thing'",
{
code: "typeof foo === 'number'",
options: [{ requireStringLiterals: true }]
},
{
code: "typeof foo === \"number\"",
options: [{ requireStringLiterals: true }]
},
{
code: "var baz = typeof foo + 'thing'",
options: [{ requireStringLiterals: true }]
},
{
code: "typeof foo === typeof bar",
options: [{ requireStringLiterals: true }]
},
{
code: "typeof foo === `string`",
options: [{ requireStringLiterals: true }],
parserOptions: { ecmaVersion: 6 }
},
{
code: "`object` === typeof foo",
options: [{ requireStringLiterals: true }],
parserOptions: { ecmaVersion: 6 }
},
{
code: "typeof foo === `str${somethingElse}`",
parserOptions: { ecmaVersion: 6 }
},

// Babel-specific test cases.
{
code: "typeof BigInt(Number.MAX_SAFE_INTEGER) === 'bigint'"
},
{
code: "'bigint' === typeof BigInt(Number.MAX_SAFE_INTEGER)"
},
{
code: "typeof BigInt(Number.MAX_SAFE_INTEGER) === 'bigint'",
options: [{ requireStringLiterals: true }]
},
],
invalid: [
{
code: "typeof foo === 'strnig'",
errors: [{ message: "Invalid typeof comparison value.", type: "Literal" }]
},
{
code: "'strnig' === typeof foo",
errors: [{ message: "Invalid typeof comparison value.", type: "Literal" }]
},
{
code: "if (typeof bar === 'umdefined') {}",
errors: [{ message: "Invalid typeof comparison value.", type: "Literal" }]
},
{
code: "typeof foo !== 'strnig'",
errors: [{ message: "Invalid typeof comparison value.", type: "Literal" }]
},
{
code: "'strnig' !== typeof foo",
errors: [{ message: "Invalid typeof comparison value.", type: "Literal" }]
},
{
code: "if (typeof bar !== 'umdefined') {}",
errors: [{ message: "Invalid typeof comparison value.", type: "Literal" }]
},
{
code: "typeof foo != 'strnig'",
errors: [{ message: "Invalid typeof comparison value.", type: "Literal" }]
},
{
code: "'strnig' != typeof foo",
errors: [{ message: "Invalid typeof comparison value.", type: "Literal" }]
},
{
code: "if (typeof bar != 'umdefined') {}",
errors: [{ message: "Invalid typeof comparison value.", type: "Literal" }]
},
{
code: "typeof foo == 'strnig'",
errors: [{ message: "Invalid typeof comparison value.", type: "Literal" }]
},
{
code: "'strnig' == typeof foo",
errors: [{ message: "Invalid typeof comparison value.", type: "Literal" }]
},
{
code: "if (typeof bar == 'umdefined') {}",
errors: [{ message: "Invalid typeof comparison value.", type: "Literal" }]
},
{
code: "if (typeof bar === `umdefined`) {}",
parserOptions: { ecmaVersion: 6 },
errors: [{ message: "Invalid typeof comparison value.", type: "TemplateLiteral" }]
},
{
code: "typeof foo == 'invalid string'",
options: [{ requireStringLiterals: true }],
errors: [{ message: "Invalid typeof comparison value.", type: "Literal" }]
},
{
code: "typeof foo == Object",
options: [{ requireStringLiterals: true }],
errors: [{ message: "Typeof comparisons should be to string literals.", type: "Identifier" }]
},
{
code: "typeof foo === undefined",
options: [{ requireStringLiterals: true }],
errors: [{ message: "Typeof comparisons should be to string literals.", type: "Identifier" }]
},
{
code: "undefined === typeof foo",
options: [{ requireStringLiterals: true }],
errors: [{ message: "Typeof comparisons should be to string literals.", type: "Identifier" }]
},
{
code: "undefined == typeof foo",
options: [{ requireStringLiterals: true }],
errors: [{ message: "Typeof comparisons should be to string literals.", type: "Identifier" }]
},
{
code: "typeof foo === `undefined${foo}`",
options: [{ requireStringLiterals: true }],
parserOptions: { ecmaVersion: 6 },
errors: [{ message: "Typeof comparisons should be to string literals.", type: "TemplateLiteral" }]
},
{
code: "typeof foo === `${string}`",
options: [{ requireStringLiterals: true }],
parserOptions: { ecmaVersion: 6 },
errors: [{ message: "Typeof comparisons should be to string literals.", type: "TemplateLiteral" }]
},

// Babel-specific test cases.
{
code: "typeof foo === 'bgiint'",
errors: [{ message: "Invalid typeof comparison value.", type: "Literal" }]
},
{
code: "'bignit' === typeof foo",
errors: [{ message: "Invalid typeof comparison value.", type: "Literal" }]
},
]
});