eslint-plugin-unicorn icon indicating copy to clipboard operation
eslint-plugin-unicorn copied to clipboard

Rule proposal: `prefer-private-class-fields`

Open sindresorhus opened this issue 3 years ago • 7 comments

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/Private_class_fields

Prefer private fields over the convention of underscore prefixed names.

This feature requires Node.js 12, so we cannot add it to the recommended preset until April 2021 (date of Node.js 10 obsoletion).

Does ESLint support this feature yet?

Fail

class Foo {
	static _PRIVATE_STATIC_FIELD

	_privateField

	_privateMethod() {
		return 'hello world'
	}
}

Pass

class Foo {
	static #PRIVATE_STATIC_FIELD

	#privateField

	#privateMethod() {
		return 'hello world'
	}
}

sindresorhus avatar Jan 01 '21 17:01 sindresorhus

This is now accepted.


But it's blocked by:

Does ESLint support this feature yet?

sindresorhus avatar Jan 22 '21 19:01 sindresorhus

No longer blocked

fregante avatar Dec 17 '21 12:12 fregante

I've already tried to implement this the other day, my experience on using private fields, I really need proposal-destructuring-private

const {a, b, c, d} = this
const e = this.#e

awkward!

fisker avatar Dec 17 '21 12:12 fisker

@fisker I would argue having to use a _ prefix to pseudo hide properties/methods is also awkward. I don't think lack of destructuring is awkward enough to not use private fields. It's just a minor inconvenience. The proposal-destructuring-private thing will probably not land in Node.js until Node.js 20 at the earliest, which means packages will not be able to use it until 2025.

sindresorhus avatar Jan 09 '22 01:01 sindresorhus

One thing to consider is that #private fields and proxies do not work together. References:

  1. https://github.com/tc39/proposal-class-fields/issues/106
  2. https://github.com/evanw/esbuild/issues/1969

bbugh avatar Oct 04 '22 12:10 bbugh

in regards to destructuring-private

i have also had to do:

const a = this.#a
const b = this.#b
const c = this.#c

And I agree that it feels a bit awkward and inconvenient. but not something that's bothering me that much. i did found that it could be just simpler to just have one single private property bag where i then store all my things

const {a, b, c} = this.#bag || { }

i rather prefer # over soft private keyword like in typescript that don't change anything. esbuild can mangle private class fields down to just 1-2 letter words resulting in better compression and things stay private as it should be doing. and it's easier to recognize that some random piece of code is making use of private class fields in some middle of the code.

jimmywarting avatar Jun 02 '23 13:06 jimmywarting

{
  'no-restricted-syntax': [
    'error',
    {
      selector: ':matches(PropertyDefinition, MethodDefinition)[accessibility="private"]',
      message: 'Use #private instead',
    },
  ],
}

playground

jimmywarting avatar Sep 14 '23 07:09 jimmywarting