Mixing TypeScript generic types loosely

Let's explore a simple example of typescript mixins:

import { Observable, of } from 'rxjs';

class Service<TDataType> {
  public foo(f: TDataType): Observable<TDataType> { return of(f); }
}

type GConstructor<T = {}> = new (...args: any[]) => T;
type ServiceConstructible<TDataType> = GConstructor<Service<TDataType>>;

function applyBarMixin<TDataType, TBase extends ServiceConstructible<TDataType>>(Base: TBase) {
  
  return class BarService extends Base{
    public bar(b: TDataType): Observable<TDataType> {
      return of(b);
    }
  };
}

After applying this mixin, the argument and return type of b() become unknown:

const FooBar = applyBarMixin(Service<number>);

const service = new FooBar();
let x = service.bar(1);
// x: unknown

Even the argument of bar becomes unknown! What could be the issue here?

TS Playground

Answer №1

Although the mixin itself is functioning correctly, the type error can be found within the service class. Service<number> represents an instance of the service class and not the class itself.

Below is the corrected version:

import { Observable, of } from 'rxjs';

class Service<TDataType> {
  public foo(f: TDataType): Observable<TDataType> { return of(f); }
}

type GConstructor<T = {}> = new (...args: any[]) => T;
type ServiceConstructible<TDataType> = GConstructor<Service<TDataType>>;

function applyBarMixin<TDataType, TBase extends ServiceConstructible<TDataType>>(Base: TBase) {
  return class BarService extends Base {
    public bar(b: TDataType): Observable<TDataType> {
      return of(b);
    }
  };
}

const FooBar = applyBarMixin(Service);

const service = new FooBar<number>();
let x = service.bar(1);  // x: Observable<number>

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

Could one retrieve the value of a type and save it as a constant?

Can I achieve something similar to this: type YesType = true; const myVar = GetTypeValue<YesType>(); // In this instance, the value true is assigned Is it feasible to assign other fixed values to constant variables like in C++? ...

Quick tip: Adding a close 'X' button to an ng-bootstrap popover

As a newcomer to angular 5, I have been working on adding an 'x' button in the top right corner of a popover. Once this 'x' is clicked, the popover should be closed. Is there a way to achieve this using ng-bootstrap popover? Below is my ...

Facilitating the integration of both Typescript and JavaScript within a Node application

We are currently integrating Typescript into an existing node project written in JS to facilitate ongoing refactoring efforts. To enable Typescript, I have included a tsConfig with the following configuration: { "compilerOptions": { "target": "es6", ...

To close the Muix DateTimePicker, simply hit the Escape key or click anywhere outside of the picker

I'd like the DateTimePicker to only close when the user presses the action buttons, not when they click outside or press Escape. Unfortunately, I haven't found any props to control this behavior yet. <DesktopDatePicker closeOnSelect={false} s ...

Troubleshooting Angular 2 Component: Why is console.log not functioning in Typescript?

I'm fairly new to both Angular2 and typescript. Given that typescript is a superset of javascript, I assumed that functions like console.log would function as expected. Interestingly, console.log works perfectly in .ts files when placed outside a comp ...

Fixing the "tl-node is not recognized" error in VS Code and TypeScript

After installing VS Code, I am struggling to figure out how to compile TypeScript code in VSCODE. Some resources mention that VSCODE includes a "stable" version of TypeScript, while others suggest installing TypeScript separately. When I try to write the ...

Eliminate any unnecessary padding from elements in angular2 components

Is there a way to remove the automatic padding added to new components in angular2? I am facing this issue with the header of my project, as shown in the image below: I attempted to eliminate the padding by setting it to 0 in styles.css file located outsi ...

Combine all TypeScript enums into a single one

Looking for a way to combine two separate enums into one for easier use. export enum ActionTypes1 { ClearError = 'CLEAR_ERROR', PrependError = 'PREPEND_ERROR', } export enum ActionTypes2 { IncrementCounter = 'INCREMENT_COUNT ...

Removing background from a custom button component in the Ionic 2 navbar

Q) Can someone help me troubleshoot the custom component below to make it resemble a plus sign, inheriting styling from the <ion-buttons> directive? In my navbar, I've included a custom component: <notifications-bell></notifications-be ...

Unable to retrieve query within async function, unable to import graphql queries externally

Is there a way to fetch characters from the parent component when a property changes and utilize these props? I attempted to use the useQuery function within a method and execute this method on prop change, but it seems like something is not functioning co ...

Press the key to navigate to a different page

I have an input field for a search box. I want it so that when I enter my search query and press enter, the page navigates to another page with the value of the input included in the URL as a query string. How can I achieve this functionality? Thank you ...

What is the best way to trigger a mat-menu to open with just one click, while also automatically closing any other open menus at

I've encountered an issue where if there are multiple menus in the header, opening a menu for the first time works fine. However, if a menu is already open and I try to open another one, it doesn't work as expected. It closes the previously opene ...

A guide on utilizing portals in Next.js to move a child element beyond its direct parent container

Current Setup Wrapper export const ContainerComponent = () => { return (<ChildComponent/>); } Child Component export const ChildComponent = () => { return ReactDOM.createPortal( <aside> <div>{"I am a c ...

Encountering an ERROR with the message "Error: NG0100: ExpressionChangedAfterItHasBeenCheckedError" while attempting to apply a filter to

My mat table includes a filter that utilizes chips to sort by multiple criteria. Upon my initial attempt to filter and save the criteria, I encountered an error called ExpressionChangedAfterItHasBeenCheckedError. The error message indicates a transition f ...

Angular 2 GET request returns a 404 error

I have been attempting to reproduce the ngPrime datatable demo from this Github repository. Currently, I am working with the most recent version of Angular (4) and using angular-cli in development mode. Placing a JSON file into my app folder where the serv ...

Pressing Enter in a Material-UI Dialog does not trigger form submission

I am currently facing an issue with my modal dialog component. I have two buttons within the dialog, with one functioning as a submit button. My goal is to make the 'Enter' key trigger the submit action as well. Below is the code snippet for thi ...

How can I ensure thorough test coverage without relying on Testbed?

We have implemented some custom form control components with decorators as follows: @Component({ selector: 'value-selector', templateUrl: './selector.component.html', styleUrls: ['./selector.component.scss'], provid ...

Receiving data from a service in Angular 2 with rxjs subscribe throws an error: it is not a

I've recently started working with Angular and I'm encountering an issue when trying to pass the _newArray to my child component using a shared service. Service fetchData(): Observable < any > { return forkJoin(this.fetchQuestions(), th ...

Step-by-step guide on developing an AngularJs provider using TypeScript

As I've developed a Directive that incorporates various Css classes, it would greatly enhance its flexibility if the Css classes could be configured at Application start within the config section. I believe utilizing a provider is the appropriate appr ...

Using React and Typescript: Populating an array within a For Loop using setTimeout is not happening sequentially or at all

I'm currently working on a function that animates images of random cars moving across the screen. My goal is to stagger the population of the "carsLeft" array using setTimeout, where I will eventually randomize the delay time for each car. Everything ...