UNPKG

@livy/util

Version:
68 lines (67 loc) 2.52 kB
import { Class } from './types'; /** * From an object type T create the type that does not have any conflicts with T */ type NoConflict<T> = { [key: string]: any; } & Partial<T>; /** * Like NoConflict<T>, but for class types */ type NoConflictClass<T extends Class.Any> = Class.Any<NoConflict<Class.InstanceType<T>>>; /** * Below is my personal approach to TypeScript mixins. * It's a slightly altered approach derived from regular mixin classes. * @see https://mariusschulz.com/blog/mixin-classes-in-typescript * * Advantages: * - Built-in support for extending abstract classes (possible with mixin classes but requires annoying amounts of additional boilerplate) * - Type-hinting for super() calls in classes which extend mixins * * Disadvantages: * - Additional boilerplate through the "Mixin" wrapper * This is however compensated by omitting other boilerplate (manual type-hinting). */ export declare namespace Mixin { /** * A Function that takes a class T and returns a class U that extends T */ interface Extender<T extends Class.Any, U extends Class.MakeConstructable<T>, V extends any[]> { (Base: T, ...additionalArgs: V): U; } /** * A generic function with a class type T that takes a class type U * (which must not be conflicting with T) and returns the intersection of T and U */ interface Wrapper<T extends Class.Constructable, V extends any[]> { <U extends NoConflictClass<T>>(Base: U, ...additionalArgs: V): U & T; } } /** * @param extender A callback which receives a base class T and returns a class U that extends T. * May take an arbitrary number of additional arguments for more fine-grained control. * @return A function which can be passed a base class and returns a new class extending it * * @example Basic example * const WriteAccess = Mixin(_ => class extends _ { * write(file: string, content: string) { * // Do some write action * } * }) * * class User { * constructor(protected name: string) {} * } * * class PrivilegedUser extends WriteAccess(User) { * constructor(name: string, protected role: 'editor' | 'admin') { * super(name) // <- type-hinted! * } * * method() { * this.write('/some/file/path', 'some content') // <- type-hinted! * } * } */ export declare function Mixin<T extends Class.Constructable, U extends Class.MakeConstructable<T>, V extends any[]>(extender: Mixin.Extender<T, U, V>): Mixin.Wrapper<U, V>; export {};