Typedoc: Support for Mixins

Created on 27 Feb 2019  路  16Comments  路  Source: TypeStrong/typedoc

Hello,

It seems typedoc does not support documenting typescript mixins? Or it can be done with some clever trick? Please advise.

Mixin pattern

The mixin pattern in TypeScript can be defined like this:

Supporting definitions:

export type AnyFunction<A = any> = (...input: any[]) => A
export type AnyConstructor<A = object> = new (...input: any[]) => A

export type Mixin<T extends AnyFunction> = InstanceType<ReturnType<T>>
export const MyMixin =
    <T extends AnyConstructor<AlreadyImplements & BaseClass>>(base : T) =>

// internal mixin class
class MyMixin extends base {
    someProperty : string = 'initialValue'

    someMethod() {
    }
}

// the "instance type" of this mixin
export type MyMixin = Mixin<typeof MyMixin>
// or (supports recursive type definition)
export interface MyMixin extends Mixin<typeof MyMixin> {}

Sample 1

The sample mixins can be found here: https://github.com/bryntum/chronograph/blob/master/src/graph/Node.ts#L5
In this example, we define the WalkableForwardNode mixin, which includes (or must already implement) WalkableForward mixin and enhances it with some additional logic.

Currently typedoc does not recognize it at all, all we have is the documentation of the mixin function:
image

No documentation is available for the internal mixin class, which is the most important piece of the mixin. Also, there's no docs for the mixin instance type alias. It does not appear in the docs index at all.

Sample 2

One can also use the interface to declare the type of the mixin instance: https://github.com/bryntum/chronograph/blob/master/src/chrono/Atom.ts#L182

This is an alternative notation, which allows for recursive type definitions. It does appear in the docs, however it does not contain the properties of the mixin class:
image

Reproduce

To reproduce you can clone the chronograph: https://github.com/bryntum/chronograph/
Then, npm install and npm run docs

Mixins are very flexible and type-safe way of combining behaviors, they should be supported by the typedoc I think. I'm very interested in this feature and volunteering for any helper tasks, just ping me [email protected]

bug

All 16 comments

Perhaps someone from the dev team can take a quick look at this issue and point me to the right direction? (I'm willing to fix/implement this myself) Some guidance, pointing to the file to start at is much appreciated.

I've created a fork with the Mixin code added to the examples folder: https://github.com/SamuraiJack/typedoc/commit/3f5076728d4eefd1de64432b78d65680ebcf9ea6
should be very easy to start investigation.

More about the modern mixin pattern: https://www.bryntum.com/blog/the-mixin-pattern-in-typescript-all-you-need-to-know/

I'm making progress and will submit a PR with mixin support soon.

Great! Thanks. Please let us know if you need any help.

Resolved in #990

Reopening this thread because I have been trying to generate mixin documentation and although I can get some results, just having a list of the mixin functions (and the class names if the mixin class is not anonymous) does not seem to be very useful. It would be great to have links to the types themselves so what has been exposed in the final type can be understood by the documentation reader.

I am trying to generate documentation for the mixin sample in: https://mariusschulz.com/blog/mixin-classes-in-typescript

I get this (giving names to the classes the mixin functions create):

Screen Shot 2020-03-26 at 6 01 13 PM

and my index.ts is:

import {User} from './user';
import {Timestamped} from './timestamped';
import {Tagged} from './tagged';

const SpecialUser = Timestamped(Tagged(User));
export type SpecialUser = typeof SpecialUser;

NOTE: I am using TypeDoc 0.16.11 as the latest is giving me issues: ts.isIdentifierOrPrivateIdentifier is not a function.

BTW, my ultimate goal would be to be able to expose the final mixed type as a type and be able to access/see everything that has been mixed: properties, methods, etc.

BTW, my ultimate goal would be to be able to expose the final mixed type as a type and be able to access/see everything that has been mixed: properties, methods, etc.

@judax check the https://www.bryntum.com/blog/the-mixin-pattern-in-typescript-all-you-need-to-know/

and stay tuned for the part 2

Thanks. Saw that post, but do you mean that the support in TypeDoc for mixins will improve soon?

If I can make an ask, it would be great to now just have the links to the mixin types in the list but also show the whole list of properties and methods that are mixed together and available for the final type/const.

Try writing your mixins in the notation suggested in the post and then generate the documentation. You should be able to see all properties (including inherited) in the created type.

Oh, I see. What version of TypeDoc has mixin support?

NOTE: I am using TypeDoc 0.16.11 as the latest is giving me issues: ts.isIdentifierOrPrivateIdentifier is not a function.

The Mixin support SamuraiJack built was released with 0.15.
Re: latest version - #1257

Thanks.

I did a quick test with the following code (based on the article):

/** @ignore */
type AnyFunction<A = any> = (...input: any[]) => A;
/** @ignore */
type AnyConstructor<A = Object> = new (...input: any[]) => A;
/** @ignore */
type Mixin<T extends AnyFunction> = InstanceType<ReturnType<T>>;

class MyClass {
  myClassMethod(): void {
  }
}

interface MyInterface1 {
  myInterface1Method(): void;
}

/** @ignore */
const MyMixin1 = <T extends AnyConstructor<MyClass>>(base : T): AnyConstructor<MyInterface1>&T =>
  class MyMixin1 extends base {
    myInterface1Method(): void {
    }
  };

/** @ignore */
type MyMixin1 = Mixin<typeof MyMixin1>;

interface MyInterface2 {
  myInterface2Method(): void;
}

/** @ignore */
const MyMixin2 = <T extends AnyConstructor<MyClass>>(base : T): AnyConstructor<MyInterface2>&T =>
  class MyMixin2 extends base {
    myInterface2Method(): void {
    }
  };

/** @ignore */
type MyMixin2 = Mixin<typeof MyMixin2>;

const FinalMixedType = MyMixin1(MyMixin2(MyClass));

And I am still seeing a similar result as mentioned above.

Screen Shot 2020-03-30 at 6 43 41 PM

Is this the expected result? I was expecting that the final mixin could show links to the interfaces (or at least to the mixin types).

Try class FinalMixedType extends MyMixin1(MyMixin2(MyClass)) {};

Also try --excludeNotDocumented command line option to avoid the need for @ignore.

@judax Just released the 2nd part of the blog post, with new mixin notation: https://www.bryntum.com/blog/the-mixin-pattern-in-typescript-all-you-need-to-know-part-2/
Mixins are represented as classes and have the docs as regular classes.

Creating a class that extends from the mixins works great! Thanks so much for all the help!

Was this page helpful?
0 / 5 - 0 ratings