What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

Use TypeScript’s private modifier when you need a compile-time guard against accidental access in checked TypeScript code. Choose ECMAScript #private when the restriction must hold at runtime, including for JavaScript callers, or when a base class and subclass need same-named internal fields without colliding. The right choice depends on the privacy boundary you need and the JavaScript target your project emits—not on a universal performance winner.

What TypeScript `private` and `#private` actually protect

TypeScript `private` is a type-checking restriction

A member marked private is inaccessible through ordinary dot notation in checked TypeScript code outside its class. The modifier is erased from emitted JavaScript, however, so the resulting property remains an ordinary JavaScript property. JavaScript callers can access it using normal property operations, and TypeScript documents bracket notation such as instance["secretKey"] as an escape hatch in applicable cases. This is soft privacy, not a runtime barrier. See the TypeScript Handbook’s Classes chapter and the TypeScript 3.8 release notes.

ECMAScript `#private` is enforced at runtime

A private identifier such as #secretKey must be declared in its class. It is not an ordinary property name: code outside the declaring class cannot access it through dot notation or bracket notation. Its privacy remains in emitted JavaScript, so JavaScript callers cannot use ordinary property access to bypass the boundary. The identifier belongs to the class that declares it, rather than being a string property that can be looked up by name. TypeScript describes this as hard privacy in its 3.8 release notes and Classes documentation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

How the two choices compare

Concern TypeScript private ECMAScript #private
Enforcement Compile-time/type-checking restriction; modifier is erased from JavaScript. Runtime-enforced privacy.
External access Ordinary JavaScript property access works; TypeScript documents bracket notation as an escape hatch in applicable cases. Not accessible through ordinary dot or bracket property access.
Same-named base and derived members Ordinary properties can collide; a subclass property can replace the effective value of a base-class property. Each class’s private identifier is distinct, even when the spelling matches.
Older JavaScript targets Works with older targets, including ECMAScript 3 according to the TypeScript 3.8 release notes. TypeScript 3.8 release notes state ES2015/ES6 or later for feature support; lower output targets may require WeakMap-based downleveling. The current handbook says targets of ES2021 or lower use WeakMaps.
Performance Ordinary property access; no universal comparison figure is established by the cited documentation. Runtime privacy checks or downleveled WeakMap output may affect speed; benchmark the actual compiled code if this matters.

When TypeScript `private` is the better fit

You want to prevent accidental access in TypeScript

Use private when the goal is to make internal use obvious and catch unintended access during TypeScript checking, while accepting that determined consumers or JavaScript code can still reach the property. That flexibility can be useful when tests need to inspect internals or when a consumer needs a temporary workaround for an API that is not yet available. The TypeScript handbook documents bracket notation as an escape hatch, and the 3.8 release notes describe soft privacy as a deliberate trade-off.

Your output target or compatibility requirements favor ordinary properties

The TypeScript 3.8 release notes say ordinary private properties work with all targets, including ECMAScript 3, while TypeScript’s #private support requires an ES2015/ES6-or-later target and can use WeakMaps for downlevel output. The current handbook describes WeakMap output when compiling to ES2021 or below. These statements describe different documentation contexts; inspect your project’s actual target and emitted JavaScript rather than assuming that #private always produces native private fields or that every build has the same runtime costs.

When `#private` is the better fit

You need runtime privacy from ordinary callers

Choose #private when JavaScript callers should not be able to read or write a field through ordinary property operations, or when you do not want an internal name to become an accidental property-level API. This is a stronger boundary than a TypeScript-only restriction, though it should not be treated as a complete security mechanism against an attacker with arbitrary control of the process.

Rank #2
TypeScript Programming Language - Software Engineer & Coder T-Shirt
  • TypeScript implements a superset of syntax for strictly typed development, facilitating deep static analysis and enhanced development environment integration. The compiler translates source into standard script formats, ensuring parity across any runtime.
  • TypeScript is ideal for front-end developers, full-stack engineers, and software architects who build large-scale web applications. It serves those looking to improve code excellence, reduce bugs through static checking, and maintain complex projects more.
  • Lightweight, Classic fit, Double-needle sleeve and bottom hem

Base and derived classes need separate internals with the same name

With ordinary properties, a derived class’s same-named member can overwrite the base class’s effective property value. Class-scoped private identifiers avoid that collision: a base class’s #value and a subclass’s #value are distinct private elements. This makes #private a useful choice in inheritance-heavy designs where both classes need an internal member with the same spelling. TypeScript documents this distinction in its 3.8 release notes.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

You need private methods, accessors, or a brand check

TypeScript 4.3 extended support for ECMAScript private identifiers to methods and accessors, not just fields; see the TypeScript 4.3 release notes. TypeScript 4.5 added #field in object checks. A successful check establishes that the object carries that class’s private field and allows TypeScript to narrow the value, which can be useful for checking whether an object has the class’s private brand. The feature is described in the TypeScript 4.5 release notes.

How to choose for a project

  1. Define the boundary. If checked TypeScript callers merely need a warning against accidental access, private may be sufficient. If ordinary JavaScript property access must not reach the member, use #private.
  2. Consider inheritance. If a base class and derived class need an internal member with the same spelling, prefer #private to avoid ordinary-property collisions.
  3. Check the compiler target and output. Inspect the project’s tsconfig target setting and the JavaScript it emits. Account for WeakMap-based downlevel output when applicable.
  4. Measure only if performance is material. Compare the compiled forms in the target runtime and workload. The TypeScript documentation warns that runtime checks and downleveled WeakMaps can affect speed, but does not establish a universal winner or speed ratio.

Privacy is not a substitute for a security boundary

Neither modifier should be presented as protection for sensitive data against someone who can arbitrarily control the running process. #private enforces access restrictions in JavaScript; that is a meaningful language-level boundary, but it does not secure the application or its execution environment. For secrets or data requiring stronger protection, state the threat model and use controls appropriate to it. The TypeScript handbook discusses hard privacy and its performance implications in its Classes chapter.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Do not confuse access modifiers with type compatibility

TypeScript’s private and protected members can affect whether two types are assignment-compatible: compatibility depends on members originating from the same class declaration. That is a type-system rule, not proof that a property is hidden from runtime JavaScript. The distinction is covered in the Type Compatibility documentation.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.