Repository navigation
Docs Meeting Notes: Mixins Reference Page #39118
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
extendspattern) - 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
interfacewhich extends thetypeoffor 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
interfacemerging 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.
Activity
[-]Docs review: Mixins Reference Page[/-][+]Docs Meeting Notes: Mixins Reference Page[/+]orta commentedon Jun 30, 2020
I found both the issue on recursive mixing referencing and the DTS output to not really be an issue with the class expression pattern and so I've not added them to the constraints
trusktr commentedon Jan 5, 2021
Does this issue consider the use of
protectedandprivatewithin class-factory mixins? I recall that the type workarounds don't work because mapped types can not handle protected/private properties.