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

Utilizing asynchronous operations in MongoDB with the help of Express

Creating a mobile application utilizing MongoDB and express.js with the Node.js MongoDB driver (opting for this driver over Mongoose for enhanced performance). I am aiming to incorporate asynchronous functions as a more sophisticated solution for handling ...

What is the best way to create a line graph with D3.js in order to display data that is obtained from a server-side source?

I am trying to access data from a server side link, which is as follows: The data I want to retrieve is in JSON format and looks like this: {"Id":466,"Name":"korea", "Occurren ...

Submitting form data using Vue and PHPMailer

I've been encountering an issue with submitting a contact form from a page. After submitting the form, nothing seems to happen. My tech stack includes Vue, Axios, and PHPMailer for handling this functionality. Upon inspecting the network tab, it appea ...

Converting JSON data into a table using jQuery, with certain columns hidden from view

I am currently working on developing a mobile app using jQuery Mobile and JSON. I have encountered two separate questions: 1) I have a JSON data set which includes fields such as id, name, surname, point, and mail. In my table that lists this data, I init ...

Having issues with the script not functioning when placed in an HTML document or saved as a .js file

Even though the database insertion is working, my script doesn't seem to be functioning properly. The message "successfully inserted" appears on the saveclient.php page instead of the index.html. In my script (member_script.js), I have placed this in ...

AngularJS encountered an unidentified provider: $routeProviderProvider

I've hit a roadblock with an unfamiliar provider error and can't seem to figure out what I'm missing. Here's the setup: in main.js 'use strict'; angular.module('myApp') .controller('MainCtrl', ['n ...

Maximizing the potential of $urlRouterProvider.otherwise in angular js

I am encountering an issue with redirecting to the login screen when there is no UABGlobalAdminId in my storage. I have tried using $urlRouterProvider.otherwise but it doesn't seem to be functioning properly. When I attempt to debug, the console does ...

Determination of the input parameters

Currently, I am developing an Angular application that includes a matInput field for user input. The issue I am encountering is that when the user enters a positive or negative value in the field (e.g. +5 or -5), the final output does not reflect the inten ...

The baffling quirks of variables within a Jquery loop

Unfortunately, I'm struggling to come up with a more fitting title for my question, but I'll do my best to provide a clear explanation of my issue. Here is the code snippet I am working with: let pdfInvoice_sub_template = [ {text: '{ ...

Problem with deleting or substituting symbols and character codes within a String

I am attempting to send an object called dataO from Node.js/Express/EJS to the client side. On the Node.js script side: var dataO = {"first":[20000, 14000, 12000, 15000, 18000, 19000, 22000], "second":[12000, 11000, 18000, 12000, 19000, 14000, 26000]}; var ...

Understanding the application of JSON data can be simplified by following these

I am looking to manipulate dates by either adding or subtracting them, but I am unsure of how to extract the dates from the other data present. var fetch = require('node-fetch'); fetch('https://api.nasa.gov/planetary/earth/assets?lon=100.7 ...

How can I organize the selected options from a select2 form element using a basic sorting method?

I am utilizing select2 by ivaynberg and encountering an issue with the data arrangement upon submission. Is there a method to have the results in the form submit data reflect the order in which they were selected in the select2 element, without relying on ...

Ways to successfully pass multiple parameters in Nuxt

Within Nuxt.js, when working with the code in pages/posts/_id.vue, it looks like this: <template> ...

Advantages of passing individual variables instead of the entire object from HTML to JavaScript in AngularJS

When it comes to passing the iterating object from HTML to Javascript, there are two approaches that can be taken. The first approach involves passing the iterating object as a whole, while the second approach only passes the required properties of the obj ...

Transferring data from jQuery Ajax to PHP

I'm facing a challenge in retrieving a value back to PHP that I can manipulate and save to the database. It appears that using the GET method with jQuery AJAX is not yielding the desired results. Below is the PHP code snippet where I attempt to captur ...

Creating a Rails application that dynamically fills a table with data from a

Encountering an issue with Ruby on Rails. I have a "Host Model" that contains a method which has a longer runtime. class Host < ActiveRecord::Base def take-a-while # implement logic here end Attempting to access a page where this method ru ...

Exploring the issue of $scope variable changes not reflecting in ng-show elements in AngularJS

I am in the process of creating a website that includes a video element. For those interested, here is a link to the code for my page on Plunker: http://plnkr.co/edit/5NUnZ2KET1apWwxMxjex?p=preview The video on the website utilizes the html5 video tag, a ...

Discovering active path while utilizing dynamic routes - here's how!

Whenever I click on the project element in my HeadlessCMS with the URL /projects/slug-name, the projects button in my Navbar (LinkItem) does not highlight with a background color (bgColor). How can I modify this line of code: const active = path === href / ...

Obtaining data from the following entry in JSON format using the Twitter API

I am currently developing a webpage that showcases user tweets, however I want to visually represent the gap in time between each tweet by displaying empty spaces. I have been struggling with the logic of how to achieve this task and haven't made muc ...

Guide to retrieving environment variables within React/Node.js applications running in Kubernetes pods

While setting environment variables in Kubernetes pods, I encountered an issue when trying to access them in either Node.js or React front-end code using process.env.TEST (where TEST is present in the environment as secrets), as it always returned undefine ...