Как сделать фабрику миксинов?

Хочу написать функцию, которая принимает базовый класс + массив классов, свойства и методы которых должны примешиваться к базовому, и возвращает новый класс, состоящий из свойств и методов базового класса с этими самыми примесями. С методами проблем нет, затык возникает со свойствами, особенно с приватными.
Допустим, есть такие классы, которые я хочу подмешать к классу
class SomeClass1 {
  #privateParam: string;

  constructor() {
      this.#privateParam = 'Some private value'
  }

  getPrivate() {
    return this.#privateParam;
  }
}

class SomeClass2 {
  getSomeEntities() {
    return "Hello, World!";
  }
}

// И мапа для удобства обращения
const classesMap = new Map()
classesMap.set('SomeClass1', SomeClass1)
classesMap.set('SomeClass2', SomeClass2)


Вот несколько упрощенная функция, которая сами миксины примешивает
const getMixedClass = (Class: any, classes: any[]) => {
  classes.forEach((item) => {
    Object.getOwnPropertyNames(item.prototype).forEach((name) => {
      Class.prototype[name] = item.prototype[name];
    });
  });
};


Далее мне нужна функция, которая получает, скажем, массив строк-указателей на классы-примеси и возвращает новый класс, либо сразу экземпляр класса с примешанными методами и свойствами запрашиваемых классов. Например:

const props = ['SomeClass1', 'SomeClass2']
class InitialClass {}
interface InitialClass extends SomeClass1, SomeClass2, SomeClassN {}
const instanceGenerator = (props: string[]) => {    
    getMixedClass(
        InitialClass,
        props.reduce((acc, next) => {
            if (classesMap.has(next)) {
                acc.push(classesMap.get(next))
            }
            return acc
        }, [])
    )
    return new InitialClass()
}

const x = instanceGenerator(props)
console.log(x.getSomeEntities()) // Тут все норм, возвращается "Hello, World!"
console.log(x.getPrivate()) // А вот тут ошибка - TypeError: attempted to get private field on non-instance


Если же сделать #privateParam у SomeClass1 неприватным (т.е. убрать #), то getPrivate будет возвращать undefined.
Собственно, вопрос в том, как сделать подобную "фабрику", чтобы она заработала?) Желательно, чтобы и приватные свойства поддерживались, если это, конечно, возможно.
  • Вопрос задан
  • 95 просмотров
Решения вопроса 1
Aetae
@Aetae Куратор тега TypeScript
Тлен
Без вариантов. Мешать классы в ts незя, потому что он как и js не поддерживает множественное наследование. Все методы сбоку через прототипы - не подразумевают работу с классами.
Помимо того что сам js физически не даст тебе работать с нативными приватными свойствами(#), так уже ts не даст тебе работать нормально с приватными и защищёнными(private и protected), а микс абстрактных (abstract) вообще забагован и не работает(issue у них пару лет висит на гитхабе).

В общем только крайне ограничено.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы