Проблема с созданием родительского класса

#typescript #class #oop

#typescript #класс #ооп

Вопрос:

Я изо всех сил пытаюсь создать родительский класс для этого типа «нормализатора». У меня есть пара классов, которые используют одну и ту же структуру классов. Я бы хотел, чтобы способ EmailNormalizer просто содержал часть логики внутри конструктора и имел все общие функциональные возможности, спрятанные в родительском классе.

У меня есть этот класс нормализатора электронной почты:

 export class EmailNormalizer {
  readonly TYPE: string | EmailNormalizer;
  normalized: string;
  constructor(raw: EmailNormalizer['TYPE']) {
    if (!raw) throw new Error('Invalid Email');
    if (raw instanceof EmailNormalizer) {
      this.normalized = raw.normalized;
    } else {
      const results = email.analyze(raw);
      if (results) throw new Error(`Email ${results.error}`);
      this.normalized = _normalizeEmail(raw);
    }
  }
  static normalize(raw: EmailNormalizer['TYPE']) {
    return new EmailNormalizer(raw).normalized;
  }
}
 

Вы можете использовать его двумя способами

  • new EmailNormalizer('hello@boom.com').normalize
  • EmailNormalizer.normalize('hello@boom.com')

Я пытаюсь создать общий родительский класс «нормализатора», чтобы не забыть ни одну из частей.

Это была моя первая попытка. У меня возникли проблемы со статическим методом, а затем я столкнулся с проблемами, когда попытался создать более общий метод нормализатора.

 class Normalizer<In = unknown, Out = unknown> {
  readonly TYPE: In;
  normalized: Out;
  normalize: (raw: In) => Out;
  constructor(raw: In) {
    this.normalized = this.normalize(raw);
  }
  static normalize<In, T extends typeof Normalizer>(this: T, raw: In) {
    return new this(raw).normalized;
  }
}

export class EmailNormalizer extends Normalizer<EmailNormalizer | string, string> {
  normalize = (raw: Email['TYPE']) => {
    if (raw instanceof Email) return raw.normalized;
    if (!raw) throw new Error('Invalid Email');
    const results = email.analyze(raw);
    if (results) throw new Error(`Email ${results.error}`);
    return _normalizeEmail(raw);
  };
}

function normalize<I extends any, O extends any, T extends Normalizer<I, O>>(i: T, value) {
  return new i(value).normalized;
}

// ideally
EmailNormalizer.normalize('HELLO@gmail.com');
// or
normalize(EmailNormalizer, 'HELLO@gmail.com')

 

Кто-нибудь может помочь разработать родительский класс normalize?

Должен ли этот родительский класс быть абстрактным?

Комментарии:

1. Пара вопросов: 1) вы уверены, что выполнение логики нормализации внутри конструктора в порядке? 2) вы уверены, что желание использовать общий статический метод является веской причиной для создания (потенциально) абстрактного базового класса и вообще использования наследования? 3) рассматривали ли вы возможность использования композиции вместо наследования?

Ответ №1:

Я мог бы предложить рассмотреть возможность использования композиции вместо наследования. Например, здесь был бы полезен некоторый шаблон стратегии:

 interface NormalizerStrategy<In, Out> {
  normalize: (raw: In) => Out;
}

class EmailNormalizerStrategy implements NormalizerStrategy<string, string> {
  normalize(raw: string): string {
    // pretend like there is some processing here
    const result = raw;

    return resu<
  }
}

class AgeNormalizerStrategy implements NormalizerStrategy<string, number> {
  normalize(raw: string): number {
    // pretend like there is some processing here
    const result = Number(raw);

    return resu<
  }
}

class Normalizer<In, Out> {
  constructor(private readonly strategy: NormalizerStrategy<In, Out>) {}

  normalize(input: In): Out {
    this.someProcessingCommonToAllTheStrategies(input);
    
    return this.strategy.normalize(input);
  }

  private someProcessingCommonToAllTheStrategies(data: In): void {
    // pretend like there is some processing here
  }
}

const emailNormalizer = new Normalizer(new EmailNormalizerStrategy);
const normalizedEmail: string = emailNormalizer.normalize('some email');

const ageNormalizer = new Normalizer(new AgeNormalizerStrategy);
const normalizedAge: number = ageNormalizer.normalize('some age');