Creating a factory class in Typescript that incorporates advanced logic

I have come across an issue with my TypeScript class that inherits another one. I am trying to create a factory class that can generate objects of either type based on simple logic, but it seems to be malfunctioning.

Here is the basic Customer class:

class Customer {
  static member = true;
  id:string;
  static c_type = "Basic Customer";

  makeTransaction():string {
    var transaction_id = Math.random().toString(36).substr(2, 9);
    console.log(this.constructor.toString().split ('(' || /s+/)[0].split (' ' || /s+/)[1]);
    return transaction_id;
  }

  constructor(public name:string, public dob:string) {
    this.id = Math.random().toString(36).substr(2, 9);
  }

}

This class extends Customer to produce a VIP customer:

class VIPCustomer extends Customer{
  vip_num:string;
  vip_discount:number;
  static c_type = "VIP Customer";
  constructor(public name:string, public dob:string) {
    super(name, dob);
    this.vip_num = Math.random().toString(36).substr(2, 9);
  }
}

The goal of the customer creator is to instantiate either a VIP or basic customer based on a string input, but it is currently not functioning properly.

class CustomerCreator {
  static create(event: {name:string; dob: string}, type:string) {
    console.log('Log type' + typeof type);
    if (type === 'Basic') {
      console.log('basic customer created');
      return new Customer(event.name, event.dob);
    }
    if (type === 'VIP') {
      console.log('VIP customer created');
      return new VIPCustomer(event.name, event.dob);
    }
  }
}
console.log(Customer.c_type);
console.log(VIPCustomer.c_type);
const customer_1 = CustomerCreator.create({name:'Pii', dob:'03/19'}, 'VIP');
var customer_2 = CustomerCreator.create({name:'Matthew', dob:'12/70'}, 'Basic');

//accessing attributes
console.log(customer_1.name);
console.log(customer_1.id);
//console.log(customer_1.vip_num)

If you uncomment the last print statement, the code will not compile. Additionally, the printed statements suggest that for both customers 1 and 2, a basic customer is being created despite the intended string comparison. Where could I be making an error?

Answer №1

Typescript’s type information is only available at compile time, rather than having information about types that are only known during runtime.

When CustomerCreator.create has a return type of Customer|VIPCustomer, it is then narrowed down to just Customer, so everything returned from the function is recognized by the TypeScript compiler as Customer. This illustrates the essence of the Factory pattern, where code relies on an interface rather than a specific class.

If you truly want the compiler to be aware of the exact type that CustomerCreator.create returns, you can consider using the following code snippet:

type CreatorResult = {
    Basic: Customer,
    VIP: VIPCustomer
}

class CustomerCreator {
  static create<T extends 'Basic'| 'VIP'>(event: {name:string; dob: string}, type:T): CreatorResult[T] {

It's important to note that this approach is not generally recommended.

Answer №2

It appears that the issue lies in your implementation of the create factory method, as it always returns the type Customer, even when trying to create a VIPCustomer. Furthermore, the create function seems to be returning Customer | undefined, indicating a missing default case for types other than Basic or VIP. Perhaps creating separate factory methods for each type of customer would be more suitable in this scenario, especially if there is minimal shared code between them.

class CustomerCreator {
    static create(event: { name: string; dob: string }) {
        return new Customer(event.name, event.dob);
    }

    static createVip(event: { name: string; dob: string }) {
        return new VIPCustomer(event.name, event.dob);
    }
}
console.log(Customer.c_type);
console.log(VIPCustomer.c_type);
const customer_1 = CustomerCreator.createVip({ name: 'Pii', dob: '03/19' });
var customer_2 = CustomerCreator.create({ name: 'Matthew', dob: '12/70' });

console.log(customer_1.name);
console.log(customer_1.id);
console.log(customer_1.vip_num)

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

Cannot find a function within the Promise

Here is the code snippet I am working with: var c = function(address, abiJson){ var _ = this; this.data = { wallet: false, account:{ address: false }, contract:{ addre ...

Align the text on the same horizontal line

I have been struggling with this issue for hours. Here is my Header.js <div className="navbar-inner"> <h2>Text1</h2> <h3>Text2</h3> </div> This is the content of my Header.css: .navbar-inner { ...

The argument type does not match the parameter type partial<>

While attempting to validate my Ionic React form, I encountered an error when calling the validationSchema within the useForm method. The specific error message received is as follows: Argument of type '{ validationSchema: ......' is not assignab ...

What is the best way to update the innerHTML of a date input to reflect the current value entered by the user?

Currently, my task involves extracting data from a table by obtaining the innerHTML of each row. The table contains date inputs that can be manually adjusted or generated automatically. However, the innerHTML does not update accordingly. Thus, when exporti ...

Guide to Embedding Dynamic Images in HTML Using VUE

I am venturing into the world of VUE for the first time, and I find myself in need of a header component that can display an image based on a string variable. Despite my best efforts to search for tutorials, I have not been able to find a solution. Header ...

looping through the iteration

Here is a link to my original plunker demonstration: http://plnkr.co/edit/9UBZ9E4uxAo1TXXghm1T?p=preview. In the case of div 4 (ng-if="show==4"), I am looking for a way to hide the particular div when the list is empty. Currently, each div is displayed fo ...

Incorporating Button Value from Anchor Tag Title Upon Page Load

Currently, I am working on a real estate project and facing an issue with a contact modal box. My goal is to extract the title from tag "a" and place it as the button value in the modal box. English isn't my strong suit, so please excuse any errors i ...

Creating a fade in or fade out effect in AJAX without using jQuery is a simple yet

Is there a simple way to achieve fade in or fade out effects in ajax without relying on jQuery? I'm looking for a solution that can add color or background color to make it visually appealing, especially for small web pages with poor internet connecti ...

Identify when two calendar dates have been modified

Creating a financial report requires the user to select two dates, search_date1 and search_date2, in order for a monthly report to be generated. Initially, I developed a daily report with only one calendar, where I successfully implemented an AJAX script ...

Removing a parameter from a variable in jQuery and JavaScript

I have coded something and assigned it to a variable. I now want to replace that value with another one. Just so you know, I do most of my coding in perl. Specifically, I am looking to remove the menu_mode value. Any advice on this would be greatly appre ...

Utilizing JavaScript to enable a Bootstrap 5 dropdown menu to open on hover for desktop users and be clickable for mobile users

I am currently using Bootstrap 5 to design a website and I'm facing an issue with creating a navbar dropdown. On desktop, I want the dropdown to open on hover and redirect the user to a new page when clicked. However, on mobile devices, I only want th ...

Countdown timer that counts down in reverse when the browser is minimized

I am currently working on a JavaScript project where I have implemented a countdown timer in seconds. Once the timer hits zero, it triggers a specific function. The timer functions correctly, however, if the browser enters sleep mode or is minimized, the ...

Missing ghost image appears when you drag and drop the file

New to JavaScript... As a rookie in coding, I often get interesting requests from my partner who is a kindergarten teacher. Recently, she asked me to create a "Function Machine" for her classroom activities. With some trial and error, I managed to put tog ...

Tips for creating a responsive tab indicator in Material UI?

I successfully integrated react router with material-ui and the routing system is working as expected. Clicking on a tab routes you to the corresponding component. However, I am facing an issue where the blue underline indicator that typically accompanies ...

Adjust the browser zoom level to default when navigating to a new page

My mobile site uses ajax to load pages, and I'm looking to implement a feature that resets the zoom level when a page changes. Is there an effective way to detect if a user has zoomed the view while browsing a page? Currently, I have been able to ch ...

Get started with adding a Typescript callback function to the Facebook Login Button

I am in the process of implementing Facebook login into my Angular7 application using Typescript. Although I have successfully integrated Facebook's Login Button plugin for logging in, I am facing issues with providing a callback method to the button& ...

How does the question mark symbol (?) behave when utilizing it in response? Specifically in relation to data, the API, and the fetch API

Have you encountered the curious sequence of symbols in this context? data?.name Could you explain the significance of the question mark (?) between 'data' and the period? ...

"Trouble with JavaScript boolean values in if-else conditions - not functioning as expected

While utilizing true/false values and checking if at least one of them is true, I am encountering an issue with the if/else statement not functioning as expected. Here is the code snippet: $scope.checkValues = function (qId) { var airport = $scope.air ...

What is the best method to calculate the total of multiple input values from various cells and display it in the final cell of an Angular table?

Hey there! I have a challenge where I need to calculate the sum of input values for each cell and display it dynamically in the last cell of the row. Take a look at the image below: https://i.stack.imgur.com/0iKEE.png In the image, you can see that the nu ...

Return all HTML code from the Ajax element

I can't seem to pinpoint the issue with my code. When I make an ajax call using the code below: ajax.js: function ajaxObj(meth, url){ var x = new XMLHttpRequest(); x.open(meth, url, true); x.setRequestHeader("Content-type", "application/x-www_form-u ...