Determine the type of a nested class within TypeScript

Utilizing nested classes in TypeScript is achieved through the following code snippet:

class Parent {
  private secret = 'this is secret'
  
  static Child = class {
    public readSecret(parent: Parent) {
      return parent.secret
    }
  }
}

This approach is inspired by this answer. It enables the Child class to access private properties of the Parent class.

To define a variable with the nested class type, one might first attempt the following:

type NestedType = Parent.Child
const child: NestedType = new Parent.Child()

However, an error is encountered:

'Parent' only refers to a type, but is being used as a namespace here. ts(2702)

An alternative using the typeof operator also proves unsuccessful:

type NestedType = typeof Parent.Child
const child: NestedType = new Parent.Child()

Ultimately, success is found in this revised approach:

const nestedTemplate = new Parent.Child()
type NestedType = typeof nestedTemplate
const child: NestedType = new Parent.Child()

Despite resolving the issue, this method does create an unnecessary instance of Child. Is this a limitation of the TS language?

Additionally, exploration was done with namespaces:

class Parent {
  private secret = 'this is secret'
}

namespace Parent {
  export class Child {
    public readSecret(parent: Parent) {
      return parent.secret
    }
  }
}

Unfortunately, utilizing namespaces results in the Child class losing access to the private properties of the Parent class:

Property 'secret' is private and only accessible within class 'Parent'. ts(2341)

Answer №1

To address your typing issues, consider utilizing the typeof child prototype.

class Parent {
  private secret = 'this is secret'

  static Child = class {
    public readSecret(parent: Parent) {
      return parent.secret
    }
  }
}

const child: typeof Parent.Child.prototype = new Parent.Child();
console.log(child.readSecret(new Parent()));

You can experiment with it here: Playground Link

This approach eliminates the need for instantiating any intermediary classes.

Answer №2

Utilize the interface property access notation (foo["bar"]) to interact with the Child class:

class Parent {
  private secret = 'this is secret'
  
  static Child = class {
    public readSecret(parent: Parent) {
      return parent.secret
    }
  }
}

type ParentChildProto = (typeof Parent)["Child"];

const child: InstanceType<ParentChildProto> = null!; // same as assigning to `new Parent.Child()`
child.readSecret(new Parent());

View in TypeScript Playground

Edit: Refer to built-in InstanceType for implementation details.

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

Including a 3DS card to a Stripe Client for recurring payments

I'm encountering an issue when trying to add payment cards with 3DS authentication for existing customers who already have an active monthly subscription. The objective is to allow our clients to change, remove, and add cards to the Stripe Customer ob ...

Change validators dynamically according to conditions

Scenario: At the start, there is a single text box named Name1, a date picker called DOB1, and a check box labeled Compare. Both Name1 and DOB1 are mandatory. When the checkbox is clicked, two new form controls are dynamically included, named Name2 and DO ...

Angular - Switching Displayed Information

I am currently working with Angular 4 and I am attempting to switch between contenteditable="true" and contenteditable="false" Here is what I have so far: <h1 (dblclick)="edit($event)" contentEditable="true">Double-click Here to edit</h1> Al ...

jquery dialog content vanishing upon second opening

My jQuery code is set up to display a dialog when a button is clicked. The issue I'm experiencing is that after closing the dialog and reopening it, the text area within the dialog appears empty with only three buttons visible. However, upon subsequen ...

Mastering jQuery UI: A beginner's guide to utilizing the date picker widget

This is my first venture into the world of HTML and JavaScript, so I am asking for your patience. I am trying to incorporate the Datepicker widget from jQuery UI, following the instructions on the Getting Started page. There seems to be an issue with lin ...

Safari's anchor links tend to leap higher than necessary

One of the anchor links on my website is behaving strangely in Safari, both on iPhone and MacOS. Instead of scrolling to the correct position of the anchored div, it scrolls to a random location around 400-500px higher than it should be. All other anchor l ...

``Implementing a method to save the output of an asynchronous request in a global variable for future manipulation

It's been a week and I still can't figure this out. Being new to front-end development, I'm struggling with storing the response from subscribe in a global variable for future use. ngOnInit(): void { this.http.get<APIResponse>('ur ...

Is there a way to use ajax to dynamically monitor the presence of a file in real-time?

Is there a way to automatically observe the status of a file using ajax without having to manually refresh it with a button? ...

The online server is unable to access the route from the ajax function in a separate JavaScript file

I am currently working on a Laravel project where each view page has its own separate JS file. However, I have encountered an issue when trying to access route functions from AJAX post or get calls on the online server (Digital Ocean). The error message I ...

Storing redux dispatch action using the useRef hook in Typescript

Currently, I am attempting to store the redux action dispatch in a React reference using useRef. My goal is to be able to utilize it for aborting actions when a specific button is clicked. Unfortunately, I am facing challenges with assigning the correct ty ...

Angular: How to Disable Checkbox

Within my table, there is a column that consists solely of checkboxes as values. Using a for loop, I have populated all values into the table. What I have accomplished so far is that when a checkbox is enabled, a message saying "hey" appears. However, if m ...

Accessing elements in AngularJS through ng-click function

According to information provided in this answer, it is necessary to pass the $event object to the ng-click function in order to access the target element. $scope.setMaster = function(obj, $event){ console.log($event.target); } Although using event.t ...

Vue allows a child component to share a method with its parent component

Which approach do you believe is more effective among the options below? [ 1 ] Opting to utilize $emit for exposing methods from child components to parent components $emit('updateAPI', exposeAPI({ childMethod: this.childMethod })) OR [ 2 ] ...

The issue of Angular's ng-repeat view not refreshing after a search query remains unresolved

Having some trouble with updating a results array in AngularJS using a service call. After submitting a form and calling the service, I set up my callbacks with .then() on the promise object. However, the view only updates when I start deleting characters ...

How to Use JavaScript Function to Rotate an Entire Webpage

For my final project in a web design class, we were tasked with creating a website that showcases our skills. I've completed the assignment and now I want to add some interesting features to make it stand out. I'm interested in using -webkit-tra ...

Deleting content in a text area when specific text is entered

Is there a way to clear the textarea value if I type in <br>? The code I have right now is shown below. I understand that this may seem like an odd request, but I am experimenting with a typing effect. function eraseText() { document.getElemen ...

Authentication failed due to Bcrypt.compare() returning invalid credentials

const express = require('express'); const router = express.Router(); const auth = require('../../middleware/auth'); const bcrypt = require('bcryptjs'); const jwt = require('jsonwebtoken'); const config = require(&apo ...

Step-by-step guide on displaying elements within an array of objects

Upon receiving an object from a website, I discovered that it includes an array of objects along with other parameters. When I use console.log(req.body.cart), the output is [ { title: 'iphone 6', cost: '650' } ], but I only require the ...

NodeJS Request Body Not Populated

Currently operating with node using [email protected] and [email protected]. Within my jade page, there exists a property like this: input(type='text',class='form-control', placeholder="Username", name='username', ...

What is the best way to restrict a React input field to have values within the minimum and maximum limits set by its

As a newcomer to React, I am working on restricting my input to values between -10 and 10. Currently, the input is set up to accept any value, and I am utilizing hooks like useState and useEffect to dynamically change and set the input value. My goal is ...