diff --git a/common/changes/@rushstack/eslint-plugin/native-private-null_2026-08-19-22-58-08.json b/common/changes/@rushstack/eslint-plugin/native-private-null_2026-08-19-22-58-08.json new file mode 100644 index 00000000000..f16f9e815e4 --- /dev/null +++ b/common/changes/@rushstack/eslint-plugin/native-private-null_2026-08-19-22-58-08.json @@ -0,0 +1,9 @@ +{ + "changes": [ + { + "packageName": "@rushstack/eslint-plugin", + "comment": "Fix no-new-null false positives for ECMAScript private class members.", + "type": "patch" + } + ] +} diff --git a/eslint/eslint-plugin/src/no-new-null.ts b/eslint/eslint-plugin/src/no-new-null.ts index 36d3e82db74..9c2774f6df1 100644 --- a/eslint/eslint-plugin/src/no-new-null.ts +++ b/eslint/eslint-plugin/src/no-new-null.ts @@ -9,6 +9,7 @@ type Options = []; interface IAccessible { accessibility?: TSESTree.Accessibility; + key?: TSESTree.Node; } const noNewNullRule: TSESLint.RuleModule = { @@ -37,11 +38,15 @@ const noNewNullRule: TSESLint.RuleModule = { create: (context: TSESLint.RuleContext) => { /** - * Returns true if the accessibility is not explicitly set to private or protected, e.g. class properties, methods. + * Returns true unless a class member uses protected, TypeScript-private, or ECMAScript-private syntax. */ function isPubliclyAccessible(node?: IAccessible): boolean { const accessibility: TSESTree.Accessibility | undefined = node?.accessibility; - return !(accessibility === 'private' || accessibility === 'protected'); + return ( + accessibility !== 'private' && + accessibility !== 'protected' && + node?.key?.type !== AST_NODE_TYPES.PrivateIdentifier + ); } /** diff --git a/eslint/eslint-plugin/src/test/no-new-null.test.ts b/eslint/eslint-plugin/src/test/no-new-null.test.ts index 7ae2fdf8045..87542636f2c 100644 --- a/eslint/eslint-plugin/src/test/no-new-null.test.ts +++ b/eslint/eslint-plugin/src/test/no-new-null.test.ts @@ -104,6 +104,17 @@ ruleTester.run('no-new-null', noNewNullRule, { ' }', '}' ].join('\n') + }, + { + code: [ + 'class NativePrivateNulls {', + ' #field: string | null;', + ' #propertyFunc: (value: string | null) => void;', + ' #method(value: string | null): string | null { return value; }', + ' get #value(): string | null { return this.#field; }', + ' set #value(value: string | null) { this.#field = value; }', + '}' + ].join('\n') } ] });