Description
- Date: June 17th, 2020
- Agenda
- Overview of mixin docs today
5min
- Discussion of the goals for mixin support, and how we want to document it
10min
- Shortcomings worth documenting in current mixin implementation
10min
- Open discussion:
~
Mixin Docs Today
Some folks have looked to improve it, and add their own docs:
- PR updating to 'ES2017'
- Recommendations from @DustinWehr
- Marius Schultz - Mixins (this is what the playground is based on)
- 'Real mixins with JS classes'
Mixin goals
- Show working examples
- Show work-arounds for current big issues
Today, how do we recommend it
-
Currently 2 different implementations strategies:
-
There is one library which covers a lot of mixin stuff: ts-mixer (no need to read it, it's mostly the
extends
pattern) - probably worth a sentence -
The 4.0 improvements to tuples could improve the pattern ...maybe?
How to describe short-comings
-
Roughly the static part of a class is a singleton (and doesn't vary), so you can't do something like
class A<T> extends B<T>
. The workaround is to declare the class independently.You can move the position of the generics - example and it can work
-
You can write:
export class Class1 { another: Class2 } export class Class2 { another: Class1 }
But not when it's a mixin pattern:
export const SampleMixin1 = <T extends AnyConstructor<object>>(base : T) => class SampleMixin1 extends base { another: SampleMixin2 // TS2502: 'another' is referenced directly or indirectly in its own type annotation } export type SampleMixin1 = Mixin<typeof SampleMixin1> export const SampleMixin2 = <T extends AnyConstructor<object>>(base : T) => class SampleMixin2 extends base { another: SampleMixin1 // TS2502: 'another' is referenced directly or indirectly in its own type annotation } export type SampleMixin2 = Mixin<typeof SampleMixin2> // supporting declarations for mixin pattern export type AnyFunction<A = any> = (...input: any[]) => A export type AnyConstructor<A = any> = new (...input: any[]) => A export type Mixin<T extends AnyFunction> = InstanceType<ReturnType<T>>
Workaround seems to be to create an
interface
which extends thetypeof
for the class and use that. This isn't something we love, but it makes sense. -
Mixins can't be represented in a d.ts file
- We can do it some tricky things to show some of these in .dts file
- Orta will find some working examples and include them in the Docs. Look at the DTS output for api-extractor uses mixins, and can compare their dts.
-
Mixins can't be made with decorators
Basically a decorator on a class can't mutate the shape of the class, though ts-mixer seems to do this (and you can use
interface
merging too)
Notes
The pattern is supported, and used by the Vue community in v1/v2. We think mostly by the mixin factory method.
- There's a stage 1 proposal in tc39, which is syntax sugar for the mixin factory pattern
- Maybe we should include a note on the variadic mixins
For orta
- look at the abstract constructor Add support for abstract constructor types #36392 - which could improve mixin support too.