@livy/util
Version:
Common utilities for the Livy logger
68 lines (67 loc) • 2.52 kB
TypeScript
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 {};