Why How to Access Typescript Private Members When I Shouldn't Be Able To

Why can I access TypeScript private members when I shouldn't be able to?

Just as with the type checking, the privacy of members are only enforced within the compiler.

A private property is implemented as a regular property, and code outside the class is not allowed to access it.

To make something truly private inside the class, it can't be a member of the class, it would be a local variable created inside a function scope inside the code that creates the object. That would mean that you can't access it like a member of the class, i.e. using the this keyword.

Why am I able to access private member of the class?

If you'll try:

class A {
private x: number;
}

let a = new A();
console.log(a.x);

(code in playground)

You'll get a compilation error:

Property 'x' is private and only accessible within class 'A'

The reason you're not getting that, I suspect (as I'm not an angular developer), is that you're having hero1.name in a string so the typescript compiler doesn't treat hero1 as a variable.

I bet that if you try:

let obj = new heross("name", "details");
console.log(`heross.name: ${ obj.name }`);

Then you'll get the compilation error.

The difference being ${} instead of {{}}.

If however you're asking why that's accessible at runtime, then that's because there's no notion of visibility in javascript, it doesn't get pass the compiler.


Edit

There's a difference between the angular double curly brace ({{ }}):

The double curly brace notation {{ }} to bind expressions to elements
is built-in Angular markup

Which you don't need to put into ticks, you can just use regular single/double quotes.

And the javascript template literals (${ }):

Template literals are string literals allowing embedded expressions.
You can use multi-line strings and string interpolation features with
them. They were called "template strings" in prior editions of the
ES2015 / ES6 specification

More simply:

let x = 4;
console.log(`x={{ x }}`); // outputs 'x={{ x }}'
console.log(`x=${ x }`); // outputs 'x=4'

Typescript private property subclass can't access

You need to change private to protected.
from typescriptlang.org:

TypeScript’s private #
TypeScript also has it’s own way to declare a member as being marked private, it cannot be accessed from outside of its containing class.

-- means private fields are going to be in all subclasses but you won't be able to access it.

Understanding protected #
The protected modifier acts much like the private modifier with the exception that members declared protected can also be accessed within deriving classes.

-- it's what you need, the fields which can't be access from outside but available in all subclasses.

Why are private members accessible through the square bracket notation?

When accessing object properties using indexes the compiler will treat the object like this:

interface BlueprintNode {
metadata: number[];
[key: string]: any;
}

If you then do:

let node: BlueprintNode;
node["metadata"].push("Access violation, rangers lead the way.");

You'll get the same error as with your code.

I can access private members in transpiled ES5 code from TypeScript

For the moment JavaScript doesn't have truly private members; the notion of private in TypeScript is merely there to help you preventing coding mistakes. There is a possibility that in the future, ECMAScript might introduce real private members, but until then, you can still access "private members" after transpiling.

Angular2 - should private variables be accessible in the template?

UPD

Since Angular 14, it is possible to bind protected components members in the template. This should partially address the concern of exposing internal state (which should only be accessible to the template) as the component's public API.


No, you shouldn't be using private variables in your templates.

While I like the drewmoore's answer and see perfect conceptual logic in it, implementationwise it's wrong. Templates do not exist within component classes, but outside of them. Take a look at this repo for the proof.

The only reason why it works is because TypeScript's private keyword doesn't really make member private. Just-in-Time compilation happens in a browser at runtime and JS doesn't have any concept of private members (yet?). Credit goes to Sander Elias for putting me on the right track.

With ngc and Ahead-of-Time compilation, you'll get errors if you try accessing private members of the component from template. Clone demonstration repo, change MyComponent members' visibility to private and you will get compilation errors, when running ngc. Here is also answer specific for Ahead-of-Time compilation.

Understanding public / private in typescript class

java script code that is generated is same

They produce the same JavaScript but don't have the same semantics as far as the type is concerned.

The private member can only be accessed from inside the class whereas public can be excessed externally.

More

The differences are covered here : https://basarat.gitbooks.io/typescript/content/docs/classes.html#access-modifiers

Another example

let foo = 123;

will generate the same ES5 as

const foo = 123; 

However in the first case let foo = 123;foo = 456 will compile fine but const foo = 123; foo = 456 will result in a compile time error.

Why can I access TypeScript private members when I shouldn't be able to?

Just as with the type checking, the privacy of members are only enforced within the compiler.

A private property is implemented as a regular property, and code outside the class is not allowed to access it.

To make something truly private inside the class, it can't be a member of the class, it would be a local variable created inside a function scope inside the code that creates the object. That would mean that you can't access it like a member of the class, i.e. using the this keyword.



Related Topics



Leave a reply



Submit