File tree Expand file tree Collapse file tree 1 file changed +44
-0
lines changed Expand file tree Collapse file tree 1 file changed +44
-0
lines changed Original file line number Diff line number Diff line change
1
+ type ApiExtension = { [ key : string ] : any } ;
2
+ type TestPlugin = ( instance : Base ) => ApiExtension | undefined ;
3
+ type Constructor < T > = new ( ...args : any [ ] ) => T ;
4
+
5
+ /**
6
+ * @author https://stackoverflow.com/users/2887218/jcalz
7
+ * @see https://stackoverflow.com/a/50375286/10325032
8
+ */
9
+ type UnionToIntersection < Union > = ( Union extends any
10
+ ? ( argument : Union ) => void
11
+ : never ) extends ( argument : infer Intersection ) => void // tslint:disable-line: no-unused
12
+ ? Intersection
13
+ : never ;
14
+
15
+ type AnyFunction = ( ...args : any ) => any ;
16
+
17
+ type ReturnTypeOf < T extends AnyFunction | AnyFunction [ ] > = T extends AnyFunction
18
+ ? ReturnType < T >
19
+ : T extends AnyFunction [ ]
20
+ ? UnionToIntersection < ReturnType < T [ number ] > >
21
+ : never ;
22
+
23
+ export class Base {
24
+ static plugins : TestPlugin [ ] = [ ] ;
25
+ static plugin < T extends TestPlugin | TestPlugin [ ] > ( plugin : T ) {
26
+ const currentPlugins = this . plugins ;
27
+
28
+ class NewTest extends this {
29
+ static plugins = currentPlugins . concat ( plugin ) ;
30
+ }
31
+
32
+ type Extension = ReturnTypeOf < T > ;
33
+ return NewTest as typeof NewTest & Constructor < Extension > ;
34
+ }
35
+
36
+ constructor ( ) {
37
+ // apply plugins
38
+ // https://stackoverflow.com/a/16345172
39
+ const classConstructor = this . constructor as typeof Base ;
40
+ classConstructor . plugins . forEach ( plugin => {
41
+ Object . assign ( this , plugin ( this ) ) ;
42
+ } ) ;
43
+ }
44
+ }
You can’t perform that action at this time.
0 commit comments