Enumerate the names of the private properties within the class

I am working on a problem where I need to use some of the class properties as values in a map within the class. In the example below, I have used an array instead of a map because when a property is marked private, it is not included in the keyof list. How can I specify key types if I want to include private property names?

var keys: Array<keyof A> = ["x", "y"]; // Error

class A {
  private x = 7;
  public y = 8;

  private keys: Array<keyof A> = ["x", "y"]; // Error
}

The same error occurs for both variables outside of the class and private properties within it:

Type '"x"' is not assignable to type '"y"'.

Answer №1

It's worth noting that when it comes to the private and protected properties of a class called C, they are not included in the list of keys returned by keyof C. This is intentional, as trying to access a private or protected property in this way would result in a compilation error. There has been a proposal on microsoft/TypeScript#22677 to enable mapping a type where these private/protected properties are made public, but as of TypeScript 4.9, this feature has not yet been implemented.

As demonstrated below, attempting to index into a class with private properties will cause errors:

namespace Privates {
  export class A {
    private x: string = "a";
    public y: number = 1;
    private keys: Array<keyof A> = ["x", "y"]; // Error
  }
  var keys: Array<keyof A> = ["x", "y"]; // Error
}
const privateA = new Privates.A();
privateA.y; // number
privateA.x; // error: private property
privateA.keys; // error: private property

However, if the goal is simply to hide certain properties from external users rather than making them explicitly private, a module or namespace can be used to selectively export only desired facets of the class:

namespace NotExported {
  class _A {
    x: string = "a";
    y: number = 1;
    keys: Array<keyof _A> = ["x", "y"]; // okay
  }
  export interface A extends Omit<_A, "x" | "keys"> {}
  export const A: new () => A = _A;
  var keys: Array<keyof _A> = ["x", "y"]; // okay
}

const notExportedA = new NotExported.A();
notExportedA.y; // number
notExportedA.x; // error: property not accessible
notExportedA.keys; // error: property not accessible

In the NotExported section, the internal details of the constructor and type _A are kept private. Only the necessary parts are exported through A. This approach maintains the desired behavior internally while limiting external visibility, similar to how Privates.A works. It focuses on not exposing implementation details rather than marking properties as private, recognizing that privacy in classes is more about access control than encapsulation.

Link to code

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

In socket.io, the event occurs twice in a row

I am encountering an issue with my socket.io nodejs cluster setup in my project where the same event is triggered twice. Despite trying different versions of Socket.io, the problem persists and two instances of the same event are being emitted. The current ...

Enhance the functionality of 'takeWhile' by incorporating a limit parameter, similar to how 'take' operates

I am attempting to retrieve all pages until either there are no more pages or a certain limit (let's say 10 pages) is reached. If I follow this approach: obs.pipe(expand((page) => { return service.call(page).nextPage; }), take(10), takeWhil ...

Is it necessary to also include template-only attributes in my controller's definition?

I'm working on a directive template that features a basic toggle variable. <div ng-mouseenter="$ctrl.myToggle = true" ng-mouseleave="$ctrl.myToggle = false"> ... </div> <div ng-if="$ctrl.myToggle"> ... toggled content </div> ...

Unit testing in Typescript often involves the practice of mocking

One challenge with mocking in Typescript arises when dealing with complex objects, as is the case with any strongly-typed language. Sometimes additional elements need to be mocked just to ensure code compilation, such as using AutoFixture in C#. In contras ...

Understanding type inference in TypeScript

I'm attempting to grasp the concept of inferring generics in Typescript, but I can't seem to figure out where I'm going wrong. Although my concrete example is too large to include here, I've provided a link to a small TypeScript playgro ...

What is the process for importing files with nested namespaces in TypeScript?

Currently, I am in the process of transitioning an established Node.js project into a fully TypeScript-based system. In the past, there was a static Sql class which contained sub-objects with MySQL helper functions. For instance, you could access functions ...

What is the best way to fetch data before a component is rendered on the screen?

I am facing an issue with fetching data from a local server in Node. When I try to render the component, the array 'users' from the state appears to be empty, resulting in no users being displayed on the screen as intended. What's strange is ...

Combine an array of arrays with its elements reversed within the same array

I am working with an array of numbers that is structured like this: const arrayOfArrays: number[][] = [[1, 2], [1, 3]]; The desired outcome is to have [[1, 2], [2, 1], [1, 3], [3, 1]]. I found a solution using the following approach: // initialize an e ...

Matching the types of method parameters to the types of callback function parameters in Typescript generics

I am currently working on creating a class that takes a function as a parameter in the constructor. The function can have arguments of any type. My goal is to add a method to the class that also accepts the same arguments as the function parameter, essenti ...

Do I have to wait for the HTTP get request to access the fetched object property?

I am currently working with Angular and TypeScript on a dish-detail component that is accessed through 'dishes/:id' The dish object returned has a property called components, which contains an array of objects with two properties: id: type stri ...

Filtering based on the boolean value of a checkbox in Angular

I'm struggling to implement a boolean filter for my search results, separating users with financial debt from those without. I need some guidance on how to achieve this. Data Filter @Pipe({ name: 'filter' }) export class FilterPipe implem ...

Creating a Typescript interface that includes keys from another interface

interface A{ a: string; b: string; c: string; // potentially more properties } interface B{ [K in keyof A]: Boolean; } What could be the issue with this code? My goal is to generate a similar structure programmatically: interface B{ ...

How to Unsubscribe from an Angular 2 Subscription Automatically After a Timeout

I am looking for a way to disregard the response from my API in case it takes too long to fetch. Currently, I am using this.http.get(mysqlUrl).subscribe() to retrieve the response. However, I would like to terminate that subscription if it exceeds a dur ...

Encountering issue with FullCalendar and Angular 11: Error reading property '__k' of null

I am currently utilizing the Full Calendar plugin with Angular 11 but have encountered an error message stating "Cannot read property '__k' of null". It appears to be occurring when the calendar.render() function is called, and I'm strugglin ...

What is the best approach to limit the return type of a function in JSX?

Is it possible to create a function where the return type should be a specific JSX type? For instance: const setHosting : <GitlabLogo> | <GithubLogo> = (h: Hosting) => ??? In this case, the return type must either be <GitlabLogo> or ...

The production build encountered an issue as it was anticipating 3 arguments, however, it only received

import { Pipe, PipeTransform } from '@angular/core'; @Pipe({ name: 'elipsis' }) export class ElipsisPipe implements PipeTransform { transform(text, length, clamp) { text = text || ''; clamp = clamp || '...& ...

Ways to verify the existence and non-empty status of a directory?

zip.loadAsync(files).then(function(directory:any){ if (directory.folder("Mary")){ console.log("fail"); } else{ directory.folder("Mary").forEach(function (filename: any) {Console.log(filename);}); }; } I am attem ...

How to customize Material UI Autocomplete options background color

Is there a way to change the background color of the dropdown options in my Material UI Autocomplete component? I've checked out some resources, but they only explain how to use the renderOption prop to modify the option text itself, resulting in a a ...

Leveraging Observables with ngrx for efficient async pipe implementation

Trying to create a shadow copy of pending changes using observables and ngrx has presented me with a puzzling issue: export class SearchBoxContainerComponent { filterSettings$: Observable<FilterSettings>; filterChanges: {[key:string]: any}; ...

What is the best way to switch routes in redux saga upon successful login?

Greetings! I'm a newcomer to React and I've been using React hooks and redux-saga for my project. I have a requirement where I need the router to navigate to /home upon successful login. I attempted to achieve this using connected-react-router an ...