eslint: Bug: `no-use-before-define` in combo with `export` keywords.
Environment
Node version: v17.7.2 npm version: v8.5.2 Local ESLint version: v7.32.0 (Currently used) Global ESLint version: Not found Operating System: linux 5.10.0-9-amd64 (Debian 10 Live-USB)
What parser are you using?
What did you do?
Configuration
{
"env": {
"browser": true
,"es2021": true
}
,"extends": [
"standard"
]
,"parser": "@typescript-eslint/parser"
,"parserOptions": {
"ecmaVersion": "latest"
,"sourceType": "module"
}
,"plugins": [
"@typescript-eslint"
]
,"rules": {
"no-tabs": 0
,"indent": ["error" ,"tab",{
"SwitchCase": 1
,"flatTernaryExpressions": false
,"offsetTernaryExpressions": true
}]
,"brace-style": ["error" ,"stroustrup" ,{
"allowSingleLine": true
}]
,"camelcase": ["error" ,{
"properties": "always"
,"ignoreGlobals": true
,"allow": [
"^UNSAFE_"
]
}]
,"comma-spacing": ["error" ,{
"before": true
,"after": false
}]
// Manually disable/enable blocks until this bug is fixed...
,"comma-style": ["error" ,"first"]
// ,"comma-style": ["error" ,"first", {
// "exceptions": {
// "VariableDeclaration": true
// }
// }]
// /Manually disable/enable blocks until this bug is fixed...
,"eol-last": ["error", "never"]
,"one-var": ["error" ,"consecutive"]
,"operator-linebreak": ["error" ,"before" ,{
"overrides": {
"=": "after"
}
}
]
,"space-before-blocks": ["error" ,"never"]
,"space-before-function-paren": ["error" ,"never"]
}
}
import { x } from './y.mjs'
export {
logger as default
,SomeClass
,x
}
class SomeClass{
// code
}
const logger = new SomeClass()
What did you expect to happen?
No complaint from eslint
.
What actually happened?
logger
was used before it was defined.eslint(no-use-before-define)
SomeClass
was used before it was defined.eslint(no-use-before-define)
See also demo.
Participation
- I am willing to submit a pull request for this issue.
Additional comments
What is needed for eslint
to allow exports at top of modules in combination with no-use-before-define
?
Because JavaScript processes those keywords before the actual code they represent in modules.
The style works perfectly without errors in browsers
, but eslint
forces you to place the export part at end of the file.
Yes i know i could use the export
keywords on the same line as the definition of them, but it is better for overview to place them at start like shown in code above.
That’s why i propose an exports
flag in no-use-before-define#options) to control the wanted behaviour.
I’ll currently use this work-around for my exports at top until this is fixed/added: 😞
/* eslint-disable no-use-before-define */
export {
logger as default
,SomeClass
,x
}
/* eslint-enable no-use-before-define */
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 1
- Comments: 16 (10 by maintainers)
Commits related to this issue
- feat: add `allowNamedExports` option to no-use-before-define Fixes #15710 — committed to eslint/eslint by mdjermanovic 2 years ago
- feat: add `allowNamedExports` option to no-use-before-define (#15953) Fixes #15710 — committed to eslint/eslint by mdjermanovic 2 years ago
@TriMoon ljharb is referring to our policies about stylistic rules.
@ljharb this rule was originally purely stylistic. As of es6, it can also be used to prevent TDZ errors, and the documentation for this rule does mention TDZ as one of the rationales for using the rule. Since this rule can be used for different purposes, I’m supportive of an option to disable a stylistic-only exports check so that the rule can be configured to only warn about statically determinable TDZ errors.
This rule is primarily stylistic, so by default any reference that appears before the declaration is disallowed. References to function declarations are also disallowed by default, although they are hoisted.
Hi @TriMoon, thanks for the issue!
I can reproduce this, but it isn’t a bug. This rule is mostly stylistic, so it reports references that appear before declarations even when those references do not cause runtime errors.
An option to always allow references inside
export { ... }
makes sense to me 👍