What is the proper way to assign the return value of a function within a class as the value of an attribute in TypeScript?

Imagine having a Class Factory that accepts another class Product (or its subclass) as an argument and has methods to return instantiated Products with additional modifications. Here is an example:

abstract class Product {}
class Wheel extends Product {}
class Roof extends Product {
    is_asbestos(){ return false } }
type ProductClass = {new (): Product}

class Factory {
    public product_cls: ProductClass;
    constructor(product_cls: ProductClass, private regulation_code?: number) {
        this.product_cls = product_cls;
    }
    build_for_france(){
        return new this.product_cls();
    }
    build_for_britain(){
        return new this.product_cls();
    }
}

let wheel_factory = new Factory(Wheel);
let roof_factory = new Factory(Roof, 123);
let new_roof = roof_factory.build_for_france();

new_roof.is_asbestos();  // error

An error occurs when trying to call the is_asbestos method.

The property 'is_asbestos' does not exist on the type 'Product'.

How can TypeScript be informed that the return value of that function is an instance of the product_cls class?

The workaround below works, but it might not be practical to do it for every function call.

let new_roof = <Roof>roof_factory.build_for_france();
new_roof.is_asbestos();

If attempted in the following manner, a syntax error is encountered.

build_for_france(){
    let french_product: this.product_cls = new this.product_cls();
    return french_product;
}

Finally, the version of TypeScript being used is 2.0.10, and an upgrade is possible if necessary.

Answer №1

It is essential to employ generics in order to indicate the type of product that your factory will produce.

abstract class Item {}
class Tire extends Item {}
class Door extends Item {
    has_lock(){ return true } }
type ItemType<T> = {new (): T}

class ProductionLine<T extends Item> {
    public itemClass: ItemType<T>;
    constructor(itemClass: ItemType<T>, private complianceCode?: number) {
        this.itemClass = itemClass;
    }
    create_for_USA(): T {
        return new this.itemClass();
    }
    create_for_UK(): T {
        return new this.itemClass();
    }
}

let tireFactory = new ProductionLine<Tire>(Tire);
let doorFactory = new ProductionLine<Door>(Door, 456);
let new_door = doorFactory.create_for_USA();

new_door.has_lock();  // yes

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

The inner HTML is malfunctioning: the function is not defined within the context of Angular

var table :HTMLTableElement = <HTMLTableElement> document.getElementById("test1"); var row = table.insertRow(1); var cell1 = row.insertCell(0); var cell2 = row.insertCell(1); var cell3 = row.insertCell(2); var cell4 = row.insertCell(3); var cell5 = ...

Troubleshooting Issue with Angular Property Binding for Image Dimensions

Currently, I am exploring property binding in Angular through an example. The idea is to use an image and bind its width, height, and src attributes using property binding. Surprisingly, even though there are no errors and the image renders successfully vi ...

The method for renaming a namespace when exporting it in Typescript

Suppose I am using a third-party namespace Foo in my Typescript code. I intend to create some utility functions for this module within a module called Utility.Foo. The issue here is that the original Foo would be hidden from functions defined inside Util ...

Combining Spring Boot and Angular applications for seamless integration

I am trying to connect my Spring Boot application with an Angular application that are running on different servers. When attempting to access REST API from the Angular app, the API call is successful but I encounter an error response on the UI. Acc ...

The functionality of verifying the type of an item in a list using Typescript is not functioning

In my TypeScript code, I am working with a type called NameValue and another one called MixedStuff. type NameValue = { name: string; value: string }; type MixedStuff = NameValue | string; function stripTwoChars(stuffs: MixedStuff[]): string { let st ...

Unable to locate module within a subdirectory in typescript

The issue I'm facing involves the module arrayGenerator.ts which is located in a subfolder. It works perfectly fine with other modules like Array.ts in the parent folder. However, when I introduced a new module called Sorting.ts, it started giving me ...

Welcome to Ng-Zorro, your destination for all things innovative and cutting

After including the NG-Zorro library in my project, every page I navigate to within my App displays only the NG-Zorro logo and the message "You have Arrived". I'm curious about removing this logo/text so that I can properly view my pages. I referred ...

Using Angular CLI to proxy websockets with a proxy configuration file, proxy.conf.json

I have been attempting to proxy websockets using ng serve --proxy-config proxy.conf.json in Angular CLI, but I have been unable to get it working. I keep encountering this error message: WebSocket connection to 'ws://stream/connect' failed: Erro ...

Exploring modules alias functionality in TypeScript

Initially, I believed that using path & basePath in tsconfig would allow aliases, but it appears not to be the case. "moduleResolution": "node", "baseUrl": "./src", "paths": { "@api/*": [&qu ...

Error: Typescript error at line 18 in app.ts - Cannot locate the 'server' namespace

Check out this straightforward code snippet: "use strict"; import * as express from "express"; class Server { public app: express.Application; public static start(): Server { return new Server(); } constructor() { this. ...

TS2304 TypeScript (TS) Unable to locate the specified name

Encountering an error message stating Cannot find name 'Record'. Do I need to install a specific package for this class? Severity Code Description File Project Line Suppression State Error TS2304 (TS) Cannot find name 'Record ...

The functionality of data-toggle seems to be malfunctioning within Angular 4

I'm attempting to implement the data-toggle feature to collapse and expand menu items in the navigation bar when the size is medium. I have provided the code below in an attempt to achieve this functionality, but unfortunately, it is not working as ex ...

Setting up Angular 2 on an Apache server for deployment

I am struggling to deploy my Angular 2 application on an Apache server despite following multiple guides such as this and this. I have both npm and ng installed on the server. This is what I have done so far: Cloned the entire project repository on my se ...

Uncover the mystery behind the return value of a generic function in TypeScript

I can't seem to wrap my head around why TypeScript is behaving in the way described below. Snippet 01| const dictionary: { [key: string]: unknown} = {} 02| 03| function set<T>(key: string, value: T): void { 04| dictionary[key] = value; 05| } ...

Replacing URLs in Typescript using Ionic 3 and Angular

Currently facing some difficulties getting this simple task to work... Here is the URL format I am dealing with: https://website.com/image{width}x{height}.jpg My objective is to replace the {width} and {height} placeholders. I attempted using this func ...

Setting up the view for 2-factor authentication in Umbraco 10: A guide for Angular or C# users

In my efforts to customize the two-factor authentication view for users with 2FA enabled in Umbraco, I've created a provider called UmbracoUserAppAuthenticator and used builder.Services.Configure to add the 'SetupViewPath', which is function ...

Input for Shared Component with routerLink

I'm looking to develop a shared component featuring a button that, upon clicking, redirects the user to a specified location. I want the consumer of the component to be able to define the route. How can I make this happen? My current idea is to set t ...

Utilize the useState hook to update state when changes occur in the

I currently have a functional component that utilizes a useState hook. The values it holds are sourced from my redux store, and I aim to update the state with the new store state every time an action is dispatched. At the moment, I've manually set an ...

Revamp the Bootstrap Form Upload feature

I am looking to redesign the Bootstrap Form Upload field. The main reason behind this is that in Bootstrap, the file upload field is treated as one single component, making it impossible to separate the file upload button from the file upload text. The fi ...

Utilizing the <HTMLSelectElement> in a Typescript project

What exactly does the <HTMLSelectElement> do in relation to a TypeScript task? let element = <HTMLSelectElement> document.querySelector('#id_name'); The HTMLSelectElement interface, similar to the one mentioned in TypeScript, is exp ...