My plugins and parser versions:
"babel-eslint": "^9.0.0",
"eslint": "^5.5.0",
"eslint-plugin-babel": "^5.2.0",
"eslint-plugin-flowtype": "^2.50.1",
"flow-bin": "^0.81.0",
My eslint configs:
"env": {
"browser": true,
"commonjs": true,
"es6": true
},
"extends": [
"eslint:recommended",
"plugin:react/recommended",
"plugin:flowtype/recommended"
],
"parser": "babel-eslint",
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"ecmaVersion": 2018,
"sourceType": "module"
},
"plugins": ["react", "babel", "flowtype"],
I got the problem when write this:
...
class Popup extends React.Component {
#previousRange: ?Range = null;
...
}
Class Popup
TypeError: Cannot read property 'type' of undefined
TypeError: Cannot read property 'type' of undefined
at isForInRef (..\node_modules\eslint\lib\rules\no-unused-vars.js:410:24)
at variable.references.some.ref (..\node_modules\eslint\lib\rules\no-unused-vars.js:447:21)
at Array.some (<anonymous>)
at isUsedVariable (..\node_modules\eslint\lib\rules\no-unused-vars.js:446:40)
at collectUnusedVariables (..\node_modules\eslint\lib\rules\no-unused-vars.js:569:26)
at collectUnusedVariables (..\node_modules\eslint\lib\rules\no-unused-vars.js:576:17)
at Program:exit (..\node_modules\eslint\lib\rules\no-unused-vars.js:621:36)
at listeners.(anonymous function).forEach.listener (..\node_modules\eslint\lib\util\safe-emitter.js:47:58)
at Array.forEach (<anonymous>)
at Object.emit (..\node_modules\eslint\lib\util\safe-emitter.js:47:38)
at NodeEventGenerator.applySelector (..\node_modules\eslint\lib\util\node-event-generator.js:251:26)
at NodeEventGenerator.applySelectors (..\node_modules\eslint\lib\util\node-event-generator.js:280:22)
at NodeEventGenerator.leaveNode (..\node_modules\eslint\lib\util\node-event-generator.js:303:14)
at CodePathAnalyzer.leaveNode (..\node_modules\eslint\lib\code-path-analysis\code-path-analyzer.js:630:23)
at CodePathAnalyzer.overrideLeaveNode (..\node_modules\eslint-plugin-node\lib\rules\process-exit-as-throw.js:127:27)
at Traverser.leave [as _leave] (..\node_modules\eslint\lib\linter.js:1000:32)
Process finished with exit code -1
Yes i use babel 7:
"@babel/core": "^7.1.2",
"@babel/plugin-proposal-class-properties": "^7.1.0",
"@babel/plugin-proposal-json-strings": "^7.0.0",
"@babel/plugin-proposal-object-rest-spread": "^7.0.0",
"@babel/plugin-proposal-unicode-property-regex": "^7.0.0",
"@babel/plugin-syntax-dynamic-import": "^7.0.0",
"@babel/plugin-syntax-import-meta": "^7.0.0",
"@babel/plugin-transform-dotall-regex": "^7.0.0",
"@babel/preset-env": "^7.1.0",
"@babel/preset-flow": "^7.0.0",
"@babel/preset-react": "^7.0.0",
This is my config:
...
options: {
presets: [
'@babel/preset-env',
'@babel/preset-react',
'@babel/preset-flow'
],
plugins: [
'@babel/plugin-proposal-object-rest-spread',
'@babel/plugin-proposal-unicode-property-regex',
'@babel/plugin-transform-dotall-regex',
'babel-plugin-styled-components',
['@babel/plugin-proposal-class-properties', { loose: false }],
'@babel/plugin-proposal-json-strings',
'@babel/plugin-syntax-dynamic-import',
'@babel/plugin-syntax-import-meta'
]
},
...
I still have this error when ever i type prefix# when declare a member in class. I think it must be an issue
Does it output correctly at least, or is just when you're linting? If you're doing a babel.config.js file, you don't need to wrap them in the options key. You can just
module.exports = (api) => {
const presets = [
'@babel/preset-env',
'@babel/preset-react',
'@babel/preset-flow'
];
const plugins = [
'@babel/plugin-proposal-object-rest-spread',
'@babel/plugin-proposal-unicode-property-regex',
'@babel/plugin-transform-dotall-regex',
'babel-plugin-styled-components',
['@babel/plugin-proposal-class-properties', { loose: false }],
'@babel/plugin-proposal-json-strings',
'@babel/plugin-syntax-dynamic-import',
'@babel/plugin-syntax-import-meta',
api.env('test') ? 'babel-plugin-istanbul' : '' // if you use special environmental plugins/presets, here's how to do it
];
return { plugins: plugins, presets: presets }; // or { plugins, presets }, as is usually preferred
};
I'm not trying to say that it _isn't_ a bug, just that babel changed the way it works vastly, so if you're taking advantae of the new configuration features, there's a _chance_ that the problem could be with babel as well/instead.
yes i just got when linting, babel is fine
@philong6297 did you figure out the linting issue?
Same issue here when using babel-eslint.
Digging deeper, in no-unused-vars.js it would appear target is undefined:
function isForInRef(ref) {
let target = ref.identifier.parent;
// "for (var ...) { return; }"
if (target.type === "VariableDeclarator") {
target = target.parent.parent;
}
Seems in my case (check your yarn.lock/package-lock.json) there were conflicting versions of babel-eslint in play. Adding a resolution to package.json seems to fix for me:
"resolutions": {
"babel-eslint": "^10.0.1"
}
I have created a demo of an issue:
https://github.com/SleepWalker/bug-eslint-no-unused-vars-private-fields
Adding a resolution to
package.jsonseems to fix for me
@jamiehill In my case that haven't fix anything :( the error still persists
Seems like the reason is that espree has no support for private properties
Seems like the reason is that espree has no support for private properties
But, isn't that why we use babel-eslint? To make eslint work properly with features espree does not support yet?
Ha, it is about flow types in private properties.
Minimal reproducible test:
it("typed private properties", () => {
verifyAndAssertMessages(
`
type Something = { };
class C {
#obj: Something;
}
console.log(new C());
`,
{ "no-unused-vars": 1 }
);
});
Probably we need to reimplement the no-unused-vars rule in eslint-plugin-babel.
This might be another relevant note,
Private fields and variables was linting fine for me _before_ i added 'plugin:flowtype/recommended' to my extends array in my .eslintrc.js
extends: [
'eslint:recommended',
'plugin:prettier/recommended',
'plugin:flowtype/recommended'
]
This exact issue still persists for me even if I crank all eslint & bable dependencies to their latest version. What's more, this doesn't always fail. For example in my case
This fails
#publicDeriverId: number;
#bip44Wallet: IBip44Wallet;
#derivationId: number;
#pathToPublic: Array<number>; // only this specific private field causes an error.
This passes
#publicDeriverId: number;
#bip44Wallet: IBip44Wallet;
#derivationId: number;
#pathToPublic: string; // note: this changed
Adding this totally unrelated type makes it work
type TotallyUnrelatedType = Array<number>;
export class Foo {
#publicDeriverId: number;
#bip44Wallet: IBip44Wallet;
#derivationId: number;
#pathToPublic: Array<number>;
}
This still occurs for me as well specifically when using any type alias. Primitives work as largely noted by @SebastienGllmt
class Something {
#config: string;
}
class Something {
#config: Array<string>;
}
type Example = string;
class Something {
#config: Example
}
This definitely seems to just be a parsing issue. I did see some typescript parser issues which were related that they had to fix so it makes sense.
For now the past year+ we have had to just use WeakMap to get private properties which isn't ideal but what can ya do?
type Example = {| one: string |};
const CONFIG: WeakMap<Sample, Example> = new WeakMap();
class Sample {
constructor() {
CONFIG.set(this, { one: 'hi' });
}
}
Hi! I just experienced this bug at work today :/ However, I found a different workaround that I didn't see listed here, so I'll share it, in case it can be helpful to anyone!
Basically, instead of typing the property using proper Flow annotations, I tried to cast a dummy value, and it prevented eslint from crashing on the 'type' of undefined error:
class MinimalExample {
// Toggle the comments between these two properties, the second line works!
#privateProp: Array<number> = [] // Breaks eslint :(
// #privateProp = ([]: Array<number>) // This works :) !
}
One downside is that it does not prevent the type to be "unioned" with other types in your methods if you happen to change it, say, from an array of numbers to a number proper. It will keep track of the union, at least, but I'd rather get the error at the reassignment (which works fine without the workaround, but then eslint is broken instead) than when I try using it later.
However, it does prevent inserting improper data inside the array for this example, so you couldn't push a string into it by accident, at least!
You can see that behavior if you add this to the class and uncomment one method at a time:
// Only uncomment one at a time, since the reassignment to a number breaks
// the addString below, where #privateProp will be treated as
// `Array<number> | number`.
// setNumber() {
// this.#privateProp = 42 // Shouldn't work :(
// // But at least, you'll catch it when you try to read from the array later.
// }
// addString() {
// this.#privateProp.push('42') // But this does trigger an error properly :)
// }
So I guess if you can tolerate a bit of fuzziness in the type safety in exchange for eslint working properly, this might be another good workaround!
However, this might not be necessary, as playing around with @SebastienGllmt's suggestion using @bradennapier's example made me see that adding an extra type alias seems to fix the problem, at least it did in our code where we encountered the issue. Here's the example from above:
// Fails indeed :(
type Example = string;
class Something {
#config: Example
}
So trying the "totally unrelated type" solution from above, I realized that creating a dummy alias for another alias... works? Just make sure not to use the dummy alias, but the original alias after having declared the dummy alias, strangely enough.
// Works :O !
type Example = string;
type WhyDoesThisWork = Example;
class Something {
#config: Example
// #config2: WhyDoesThisWork // This does not work actually, only the original alias works...
}
So, I guess there's two different workarounds for the problem, at least, for others that will get it.
Thank you for the issue. Now that @babel/eslint-parser has been released, we are making this repository read-only. If this is a change you would still like to advocate for, please reopen this in the babel/babel monorepo.
Most helpful comment
This exact issue still persists for me even if I crank all eslint & bable dependencies to their latest version. What's more, this doesn't always fail. For example in my case
This fails
This passes
Adding this totally unrelated type makes it work