@juzi/wechaty
Version:
Wechaty is a RPA SDK for Chatbot Makers.
73 lines (60 loc) • 1.92 kB
text/typescript
/**
* Class mixins are a pattern for sharing code between classes using standard JavaScript.
* https://lit.dev/docs/composition/mixins/
*/
import type { Constructor } from 'clone-class'
import { log } from '@juzi/wechaty-puppet'
interface PoolifyMixin<T> {
new (...args: any[]): T
pool: Map<string, T>
}
/**
* https://stackoverflow.com/a/60378737/1123955
*
* You want something like partial type parameter inference,
* which is not currently a feature of TypeScript (see microsoft/TypeScript#26242).
* Right now you either have to specify all type parameters manually
* or let the compiler infer all type parameters;
* there's no partial inference.
* As you've noticed,
* generic type parameter defaults do not scratch this itch;
* a default turns off inference.
*/
const poolifyMixin = <MixinBase extends Constructor>(mixinBase: MixinBase) => <T>() => {
log.verbose('PoolifyMixin', 'poolifyMixin(%s)', mixinBase.name)
abstract class AbstractPoolifyMixin extends mixinBase {
static _pool? : Map<string, T>
static get pool (): Map<string, T> {
/**
* hasOwnProperty() is important because we are calling this from the child classes
*/
if (!Object.prototype.hasOwnProperty.call(this, '_pool')) {
log.verbose('PoolifyMixin', 'get pool() init pool')
this._pool = new Map<string, T>()
}
return this._pool! // FIXME: why we need "!" at here?
}
public static load<L extends Constructor<T> & PoolifyMixin<T>> (
this : L,
id : string,
): T {
const existingItem = this.pool.get(id)
if (existingItem) {
return existingItem
}
const newItem = new this(id)
this.pool.set(id, newItem)
return newItem
}
constructor (...args: any[]) {
super(...args)
}
}
return AbstractPoolifyMixin
}
export type {
PoolifyMixin,
}
export {
poolifyMixin,
}