Фабричный класс машинописного текста с использованием логики

У меня есть класс typescript, наследующий другой. Я хотел бы создать фабричный класс, который создает объект одного или другого, используя базовую логику, но он не работает.

Это базовый класс для клиента:

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.info(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);
  }

}

Этот класс расширяет клиентов для создания VIP-клиента:

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);
  }
}

Создатель клиента предназначен для создания либо VIP-клиента, либо обычного клиента на основе сравнения строк, но он не работает.

class CustomerCreator {
  static create(event: {name:string; dob: string}, type:string) {
    console.info('Log type' + typeof type);
    if (type === 'Basic') {
      console.info('basic customer created');
      return new Customer(event.name, event.dob);
    }
    if (type === 'VIP') {
      console.info('basic customer created');
      return new VIPCustomer(event.name, event.dob);
    }
  }
}
console.info(Customer.c_type);
console.info(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 an attribute
console.info(customer_1.name);
console.info(customer_1.id);
//console.info(customer_1.vip_num)

Если вы раскомментируете последний оператор печати, код не скомпилируется. Операторы печати также указывают, что базовый клиент создается как для клиентов 1, так и для клиентов 2, несмотря на сравнение строк. Где я ошибаюсь?

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
0
176
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Typescript имеет только информацию о типе времени компиляции, но не информацию о типе, известную только во время выполнения.

Тип возвращаемого значения CustomerCreator.createCustomer|VIPCustomer, который сужен до Customer, поэтому все, что возвращается из этой функции, распознается компилятором ts как Customer . В этом весь смысл шаблона Factory, что ваш код опирается на интерфейс, а не на класс.

Если вы действительно хотите, чтобы компилятор знал, какой именно тип того, что возвращает CustomerCreator.create, вы можете попробовать следующий код

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

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

хотя это не рекомендуется

почему это не рекомендуется?

user25976 07.04.2019 01:31

это неправильное использование сопоставленных типов Typescript и раскрытие слишком большого количества деталей вызывающему абоненту

Austaras 07.04.2019 01:45
Ответ принят как подходящий

Ваше решение не работает, потому что фабричный метод create всегда возвращает тип Customer, поскольку VIPCustomer также является производным от Customer. Кроме того, ваша функция create возвращает не только Customer, но и Customer | undefined, потому что у вас нет регистра по умолчанию (когда тип не является ни Basic, ни VIP). Я бы просто создал несколько фабричных методов для каждого типа клиентов. В этом случае моего примера почти нет общего фрагмента кода или дополнительной обработки, фабричный шаблон становится бесполезным.

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.info(Customer.c_type);
console.info(VIPCustomer.c_type);
const customer_1 = CustomerCreator.createVip({ name: 'Pii', dob: '03/19' });
var customer_2 = CustomerCreator.create({ name: 'Matthew', dob: '12/70' });

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

Обновлен мой ответ, чтобы включить объяснение

10100111001 07.04.2019 01:38

Другие вопросы по теме