Skip to content

Commit ad59825

Browse files
Initial commit
0 parents  commit ad59825

File tree

13 files changed

+4646
-0
lines changed

13 files changed

+4646
-0
lines changed

.gitattributes

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Auto detect text files and perform LF normalization
2+
* text=auto

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
public/dist
2+
node_modules
3+
.idea

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# extend-bases: A simple library for multiple inheritance in JavaScript.
2+
3+
This library can be used to achieve multiple inheritance in JavaScript, but it sets itself apart from other libraries for multiple inheritance because it isolates the base classes and prevents the properties and methods from colliding, while still allowing easy access to the properties and methods of the base classes.
4+
5+
## Implementation details
6+
7+
This library uses Proxies, so sadly no IE11 support, but otherwise this library also imports es-shims for `Reflect.ownKeys`(ES6 but used very often and an es-shim exists for it) and `Array.prototype.flatMap`(ES2019, very new), which were found to be the bottlenecks, for some browsers.
8+
9+
This library uses proxies for easy access in the class instances, and it merges the prototypes of the base classes, but for isolation of base classes it creates a new function wrapping the method call. It’s just best to look at the source code for this.
10+
11+
## TypeScript support
12+
13+
The library is by default written in TypeScript, which you all should be using if you aren’t, for great code completion. The details of the TypeScript definitions are a bit fiddly, so it’s best not to worry about them, they work<small>, or you can just look at the source code</small>.

index.d.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/**
2+
* The type of the constructor of an object.
3+
*/
4+
export declare type Ctor = new (...params: any[]) => any;
5+
declare type AnyInstancesOf<T extends Ctor[]> = InstanceType<T[number]>;
6+
/**
7+
* Black magic.
8+
*
9+
* Note: Works only in one way.
10+
*
11+
* @internal
12+
*/
13+
declare type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
14+
/**
15+
* The type of an array containing the instances of specified constructors.
16+
*/
17+
export declare type InstancesArray<Ts extends Ctor[]> = {
18+
[I in keyof Ts]: Ts[I] extends Ctor ? InstanceType<Ts[I]> : never;
19+
} & Array<InstanceType<Ts[number]>>;
20+
/**
21+
* Specifies that the object has an array containing instances of all of the bases.
22+
*/
23+
export declare type HasBasesArray<TBases extends Ctor[]> = {
24+
readonly bases: InstancesArray<TBases>;
25+
};
26+
/**
27+
* Specifies that the object is an intersection of all of the bases.
28+
*/
29+
export declare type HasBases<TBases extends Ctor[]> = UnionToIntersection<AnyInstancesOf<TBases>> & HasBasesArray<TBases>;
30+
/**
31+
* Returns a class which when "inherits" from all of the base classes.
32+
*
33+
* This function isolates the method calls on the bases, so if any of the 2 bases share a property or method with the same name then, they will not affect each other.
34+
*
35+
* When you access a property or method directly on `this` and not on `this.bases`, and it doesn't exist on the `this` instance, then the first base class with the method/property will be the one given precedence and its method/property will be the one given.
36+
*
37+
* The returned class must be initialized with the <i><b>instances</b></i> of each of the respective base classes
38+
*
39+
* Note: There is a caveat, setting properties is a bit fiddly, if you directly set a property in the constructor and the super class has the same property name then it will be overwritten.
40+
* This is not due to this library, this is due to the inherent dynamic nature of JavaScript.
41+
* But, this library isolates the derived and base classes, ie prevents collision of their properties and methods.
42+
* Thus, to solve this problem, it is recommended use the <code>defineProperties</code> method from this library.
43+
* @param baseClasses The base classes to be inherited.
44+
*/
45+
export declare function bases<TBases extends Ctor[]>(...baseClasses: TBases): new (...baseInstances: InstancesArray<TBases>) => HasBases<TBases>;
46+
/**
47+
* Checks if the value `v` is an instance of the class `cls`.
48+
* This function takes into account the multiple base classes as well.
49+
*
50+
* @param v The value to check.
51+
* @param cls The constructor of the class.
52+
*/
53+
export declare function isInstanceOf<T extends object, TBase extends Ctor>(v: T, cls: TBase): boolean;
54+
/**
55+
* Defines the properties on the given object, the key represents the name of the property and the value as the, well, value.
56+
* Moreover, if the property name if prefixed with "readonly " then the property will be set to be readonly, ie non-writable.
57+
*
58+
* Use this function to set the properties of the objects inheriting from multiple base classes.
59+
*
60+
* @param v The object on which to define the properties
61+
* @param props A object with the keys as the property names and the values as the values of the properties.
62+
*/
63+
export declare function defineProperties<T extends object>(v: T, props: {
64+
[key: string]: any;
65+
}): void;
66+
export {};

index.js

Lines changed: 214 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

index.js.map

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)