У меня есть функция с именем Mixin
, которая принимает один аргумент. Аргумент должен быть "mixin фабрики классов".
Например, предположим, у меня есть фабричная функция mixin этого класса:
type Constructor<T = any, A extends any[] = any[]> = new (...a: A) => T
const CoolMixin = <T extends Constructor>(Base: T) => {
return class CoolMixin extends Base {
coolProp = 42
}
}
const CoolFoo = CoolMixin(class Foo {
foo = 'asdf'
})
const c = new CoolFoo()
// it works:
c.foo
c.coolProp
( ссылка на игровую площадку )
Как вы видите, он принимает базовый класс и возвращает новый класс, и он отлично работает.
У меня есть утилита Mixin
, которая принимает функцию mixin и предоставляет ей классные функции, такие как поддержка hasInstance
, кэширование против дублирующих приложений базовых классов и другие функции.
В простом JavaScript я могу использовать его так:
// Mixin returns an application of the Mixin function (a class) with
// a default base class applied (Object by default):
const CoolMixin = Mixin((Base) => {
return class CoolMixin extends Base {
coolProp = 42
}
})
// Here, CoolMixin is `class CoolMixin extends Object {...}`,
// so we can use it like a regular class:
let CoolFoo = class Foo extends CoolMixin {
foo = 'asdf'
}
// Mixin returns that class with a static `.mixin` property containing
// the original mixin function, so we can also use it as a mixin:
CoolFoo = CoolMixin.mixin(class Foo {
foo = 'asdf'
})
// either of the two versions will work the same:
const c = new CoolFoo()
c.foo
c.coolProp
Таким образом, удобство моей утилиты (помимо таких функций, как кеширование, hasInstance и т. Д.) Состоит в том, что ее можно использовать, однако она наиболее удобна. Вот еще два примера:
// suppose One and Two are mixins created with my Mixin utility.
// Use regular extension:
class Foo extends One {...}
class Bar extends Two {...}
// or compose them together:
class Baz extends One.mixin(Two) {...}
Итак, я хотел бы выяснить, как сделать набор текста для этой Mixin
утилиты в TypeScript.
Моя первая попытка следующая, которая не работает, но я думаю, что она показывает идею того, что я пытаюсь сделать:
type Constructor<T = any, A extends any[] = any[]> = new (...a: A) => T
type MixinFunction = <TSub, TSuper>(base: Constructor<TSuper>) =>
Constructor<TSub & TSuper>
declare function Mixin<TSub, TSuper, T extends MixinFunction>(mixinFn: T):
Constructor<TSub & TSuper> & {mixin: T}
// Then using it like so:
const CoolMixinFunction = <T extends Constructor>(Base: T) => {
return class CoolMixin extends Base {
coolProp = 42
}
}
const CoolMixin = Mixin(CoolMixinFunction)
const CoolFoo = CoolMixin.mixin(class Foo {
foo = 'asdf'
}
const c = new CoolFoo()
c.foo
c.coolProp
const CoolBar = class Bar extends CoolMixin {
bar = 'asdf'
})
const b = new CoolBar()
b.bar
b.coolProp
( ссылка на игровую площадку )
Как вы понимаете, я пытаюсь набрать инструмент Mixin
, чтобы он принимал функцию mixin, а тип возвращаемого значения для вызова Mixin
должен был быть классом, который генерируется из функции mixin, и этот возвращаемый класс также должен иметь свойство .mixin
, которое совпадает с типом переданной функции mixin.
Я знаю, что я делаю это неправильно. Мне не ясно, как я могу использовать здесь вывод типа.
Похоже, здесь может быть полезна новая «Вывод типа функции высшего порядка» .
Как мне добиться этой Mixin
утилиты набора текста? Могу ли я сделать это без функции высшего порядка? И как это сделать с этой функцией?