Skip to content

Docs Meeting Notes: Mixins Reference Page #39118

Closed
@orta

Description

@orta
  • Date: June 17th, 2020
  • Agenda
    1. Overview of mixin docs today 5min
    2. Discussion of the goals for mixin support, and how we want to document it 10min
    3. Shortcomings worth documenting in current mixin implementation 10min
    4. Open discussion: ~

Mixin Docs Today

Some folks have looked to improve it, and add their own docs:

Mixin goals

  • Show working examples
  • Show work-arounds for current big issues

Today, how do we recommend it

  • Currently 2 different implementations strategies:

    • handbook: Use isolated classes. Then use interface merging + a runtime function to create - play
    • playground: (mixin factory pattern) classes use extends with their list of deps - play
  • 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

  • Mixins with Generics - play

    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

  • Recusive definitions

    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 the typeof 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Docs Meeting NotesWrite-ups on the meeting every two weeks on docs topics

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions