Using Typescript to enclose the object and selectively proxying a subset of its methods

When utilizing the Test class within another class named Wrapper, I aim to be able to delegate the methods to the test instance in a universal manner, like so: this.test[method]().

In this scenario, my intention is only to delegate the fly, swim, and drive methods (all with the same signature). However, the issue lies in other methods of the Test class, which is where TypeScript raises concerns.

Within the first // 1. addEventListener, if I attempt to use keysof, TypeScript gives me an error due to the method signatures.

In the second // 2. addEventListener, I tried creating a new type called CustomMethods using the Pick utility type, but encountered the error message "

CustomMethod cannot be used as an index type
".

Is there a way to compile this code in --strict mode?

class Test {
  fly(location: string, listener: Function) {}
  swim(location: string, listener: Function) {}
  drive(location: string, listener: Function) {}

  stopFlying(birds:number[]){}
  stopDriving(racers:boolean[]){}

}

// picking specific methods from the Test type
type CustomMethods = Pick<Test, "fly" | "swim"| "drive">;


class Wrapper {
  public name: string;
  public test: Test;
  constructor(t:Test) {
    this.name = "event";
    this.test = t
  }

  // 1.
  addListener(method: keyof Test, listener: Function) {
    this.test[method](this.name, listener);
  }

  // 2.
  addListener(method: CustomMethods, listener: Function) {
    this.test[method](this.name, listener);
  }
}

typescript playground demo

Answer №1

To find the specific key you're looking for in Pick<Test, "fly" | "swim"| "drive">, be sure to use

keyof Pick<Test, "fly" | "swim"| "drive">
, not just the
Pick<Test, "fly" | "swim"| "drive">
.

Answer №2

It's almost great. In fact, it could be made even simpler by specifying the method names in a union type like this: method: "fly" | "swim"| "drive". If this type is needed elsewhere, simply create an alias for it:

type TestMethodName = "fly" | "swim"| "drive"
.

This TypeScript code can be enhanced to be more idiomatic in my opinion:

  • Use parameter properties for concise class code
  • Omit the public keyword since it is implicit, except in constructor for parameter properties
  • Opt for readonly fields when feasible to promote immutability
type TestMethodName = "fly" | "swim"| "drive";

class Wrapper {
  readonly name = "event";

  constructor(readonly test: Test) {}

  addListener(method: TestMethodName, listener: Function) {
    this.test[method](this.name, listener);
  }
}

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

Leveraging the power of NextJs and the googleapis Patch function to seamlessly relocate files and folders to a specific

I am currently working on a functionality to move specific files or folders to another folder using nextjs + googleapis. Here is the code I have been testing: const moveFileOrFolder = async () => { if (!session || !selectedItemId || !destinationFolder ...

How to set return types when converting an Array to a dynamic key Object in Typescript?

Can you guide me on defining the return type for this function? function mapArrayToObjByKeys(range: [string, string], keys: { start: string; end: string }) { return { [keys.start]: range[0], [keys.end]: range[1] } } For instance: mapArrayToObj ...

What does ngModel look like without the use of square brackets and parenthesis?

Can you explain the usage of ngModel without brackets and parentheses in Angular? <input name="name" ngModel> I am familiar with [ngModel] for one-way binding and [(ngModel)] for two-way binding, but I am unsure what it means when ngModel ...

The method to create a global generic class in TypeScript

Is there a way to globally expose the Hash class? Access Playground here export {} class Hash<K, V> { } declare global { // How can we achieve this? } window.Hash = Hash // Making it globally accessible ...

Issue: When attempting to read the length of a property in Angular 6, a TypeError is being thrown because the property is

Unable to retrieve values from an array using the TS code below: this.dataservice.get("common/public/getAllCategories", null).subscribe(data => { //console.log('categories'+JSON.stringify( data)); this.categoriesarray = data; }); var ...

The React-widgets DateTimePicker is malfunctioning and displaying an error stating that it cannot assign to the type of 'Readonly<DateTimePickerProps>'

Hello there! I am a newcomer to TypeScript and I am facing difficulty in understanding an error. Any help regarding this will be greatly appreciated. I have tried searching for solutions online and even attempted changing the version, but I am unsure of wh ...

Can we restrict type T to encompass subclasses of K, excluding K itself?

Can a generic type T be restricted to the subset of subtypes of type K, excluding K itself? I am attempting to define a type for inheritance-based mixin functions. An answer for the opposite case is provided in Question 32488309, and interestingly, this qu ...

Guide on associating user IDs with user objects

I am currently working on adding a "pin this profile" functionality to my website. I have successfully gathered an array of user IDs for the profiles I want to pin, but I am facing difficulties with pushing these IDs to the top of the list of profiles. My ...

Steps for setting up tsconfig.json for Chrome extension development in order to utilize modules:

While working on a Chrome plugin in VS Code using TypeScript, I encountered an issue with the size of my primary .ts file. To address this, I decided to refactor some code into a separate module called common.ts. In common.ts, I moved over certain constan ...

Limiting the Size of Highcharts Maps with maxWidth or maxHeight

My attempt to adjust the maxWidth of my world map using highcharts isn't altering its size. I have experimented with the following: responsive: { rules: [{ condition: { maxWidth: 500 }, ... As recomme ...

The declaration file for the 'react' module could not be located

I was exploring Microsoft's guide on TypeScript combined with React and Redux. After executing the command: npm install -S redux react-redux @types/react-redux I encountered an error when running npm run start: Type error: Could not find a decla ...

Is it feasible to have two interfaces in Typescript that reference each other?

I am facing an issue with two interfaces, UserProfile and Interest. Here is the code for both interfaces: export default interface UserProfile { userProfileId: string, rep: number, pfpUrl: string, bio: string, experience: "beginner" | " ...

Even after rigorous type checking, TypeScript continues to throw the ts2571 error when handling an unidentified variable

Consider this scenario: the code snippet below will result in an Object is of type 'unknown'. error: let obj: {[key: string]: unknown} = {hello: ["world", "!"]}; // Could be anything with the same structure let key = "he ...

The BullMQ library is optimizing performance by efficiently managing Redis connections

Currently, I'm in the process of implementing logic to efficiently reuse redis connections with bullMQ by referring to this specific section in the bullMQ documentation. My setup involves utilizing the latest BullMQ npm version (1.80.6). As per the ...

The Angular Button fails to display when all input conditions are met

I'm currently working on validating a form using this link. The requirement is simple - when an input field is invalid, the `save` button should be disabled. Conversely, when all input fields are valid, the `SAVE` button should be enabled/shown. The & ...

What is the method to create a universal type by utilizing attributes from a different type?

In building a type, I aim to create one that can accept the type of another object and generate a different type based on specific properties in that object. Illustrating this concept through code: // Definition representing the types of inputs shown on UI ...

Obtain the appropriate selection in the dropdown based on the model in Angular

I am working on a dropdown menu that contains numbers ranging from 1 to 10. Below is the HTML code for it: <div class="form-group"> <label>{{l("RoomNumber")}}</label> <p-dropdown [disab ...

Troubleshooting a Jasmine Unit Testing Error for Button Click in Angular 4

Exploring the world of Jasmine and Angular 4, I am aiming to write tests for a button functionality in a multi file upload feature. Below is the code snippet from my spec file: import { async, ComponentFixture, TestBed } from '@angular/co ...

Issue regarding locating Material-UI components while resolving TypeScript modules

I am encountering an issue with my Visual Studio 2019 (v16.3.2) React TypeScript project that involves Material-UI components. The TypeScript compiler is unable to resolve any of the @material-ui imports, resulting in errors like the one below which preven ...

Encountering a TypeScript error when attempting to utilize indexOf on a Typed Array, leading to restriction

I have been working with an Interface, where I created an array of type Interface. I am currently facing some IDE error complaints when trying to use the .indexOf method on the Array. These errors seem confusing to me, and I'm hoping someone here migh ...