This error occurs when using JavaScript private field syntax (#fieldName) in React class components without proper TypeScript or Babel configuration. Private fields require ECMAScript 2015+ targets and specific transpiler support to work correctly.
This error appears when you attempt to use ECMAScript private fields (denoted with the # prefix) in React class components without the necessary build tooling configuration. Private fields were introduced in ES2021 as a way to create truly private class properties that are completely inaccessible outside the class—unlike TypeScript's private keyword, which only enforces privacy at compile time. React class components can use private fields, but your build configuration must support transpiling this modern JavaScript syntax. TypeScript requires targeting ES2015 or higher, and Babel needs the appropriate plugins to transform private field syntax into code that works in all environments. The key distinction is that TypeScript's private keyword is erased at runtime and acts like a normal property, while ECMAScript's # private fields are enforced by the JavaScript engine itself and cannot be accessed outside the class at runtime.
Open your tsconfig.json file and ensure the target is set to ES2015 or higher:
{
"compilerOptions": {
"target": "ES2015", // or ES2016, ES2020, ESNext
"lib": ["ES2015", "DOM"],
"useDefineForClassFields": true
}
}The useDefineForClassFields option ensures proper class field semantics.
If using Babel, install the necessary plugins for private fields and class properties:
npm install --save-dev @babel/plugin-proposal-class-properties @babel/plugin-proposal-private-methodsOr with yarn:
yarn add -D @babel/plugin-proposal-class-properties @babel/plugin-proposal-private-methodsUpdate your .babelrc or babel.config.js to include the plugins:
{
"presets": [
"@babel/preset-env",
"@babel/preset-react",
["@babel/preset-typescript", {
"allowDeclareFields": true
}]
],
"plugins": [
"@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-private-methods"
]
}Note: Plugin order matters. @babel/plugin-transform-typescript must run before class-related plugins.
If you're using TypeScript's declare keyword with private fields, enable the allowDeclareFields flag:
{
"presets": [
["@babel/preset-typescript", {
"allowDeclareFields": true
}]
]
}This prevents the "declare fields must first be transformed" error.
If you need broader compatibility, use TypeScript's private keyword instead of # syntax:
class MyComponent extends React.Component {
private myField = 'value'; // TypeScript private
// Instead of:
// #myField = 'value'; // ECMAScript private
}While TypeScript's private is only enforced at compile time, it doesn't require runtime support and works with any target.
After configuration changes, clear build caches and rebuild:
# Remove node_modules and reinstall
rm -rf node_modules package-lock.json
npm install
# Clear build caches
rm -rf .cache dist build
# Rebuild
npm run buildFor create-react-app projects:
rm -rf node_modules/.cache
npm startUnderstanding Private Field Privacy Enforcement:
ECMAScript private fields using # are fundamentally different from TypeScript's private modifier. The # prefix creates a "hard private" field that cannot be accessed outside the class, even via reflection or bracket notation. This is enforced by JavaScript engines through a "brand check"—attempting to access #field on an object that doesn't have it defined will throw a TypeError.
Browser Compatibility:
Private fields are supported in modern browsers (Chrome 74+, Firefox 90+, Safari 14.1+, Edge 79+) but not in Internet Explorer. Production builds must transpile this syntax for broader compatibility.
Babel Preset Evolution:
As of Babel 7.10.0, @babel/preset-env includes support for private fields based on your browserslist targets. If targeting modern environments, you may not need explicit plugins. However, explicit plugin configuration ensures predictable behavior across all environments.
React and Class Fields:
React class components work seamlessly with private fields once properly configured. However, consider that the React team recommends function components with hooks for new code, which don't use class syntax at all.
TypeScript 3.8+ Changes:
TypeScript 3.8 introduced support for ECMAScript private fields alongside its existing private keyword. You can use both in the same codebase, choosing # for runtime privacy and private for compile-time privacy.
React Hook useCallback has a missing dependency: 'variable'. Either include it or remove the dependency array react-hooks/exhaustive-deps
React Hook useCallback has a missing dependency
Cannot destructure property 'xxx' of 'undefined'
Cannot destructure property of undefined when accessing props
useNavigate() may be used only in the context of a <Router> component.
useNavigate() may be used only in the context of a Router component
Cannot find module or its corresponding type declarations
How to fix "Cannot find module or type declarations" in Vite
Vite HMR connection failed, make sure your config is correct
How to fix "Vite HMR connection failed" in React