@ddd-ts/traits 0.0.36 → 0.0.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/dist/index.js +29 -32
- package/dist/index.mjs +34 -0
- package/package.json +20 -8
- package/dist/index.js.map +0 -1
- package/dist/index.spec.js +0 -426
- package/dist/index.spec.js.map +0 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Aetherall
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.js
CHANGED
|
@@ -1,44 +1,41 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
exports.Subtrait = Subtrait;
|
|
5
|
-
exports.Derive = Derive;
|
|
6
|
-
exports.WithDerivations = WithDerivations;
|
|
7
|
-
exports.implementsTrait = implementsTrait;
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
//#region src/index.ts
|
|
8
4
|
function Subtrait(superTraits, factory) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
};
|
|
5
|
+
return {
|
|
6
|
+
factory,
|
|
7
|
+
superTraits,
|
|
8
|
+
symbol: Symbol()
|
|
9
|
+
};
|
|
15
10
|
}
|
|
16
11
|
function Derive(...traits) {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
for (const trait of traits) {
|
|
23
|
-
current[trait.symbol] = true;
|
|
24
|
-
}
|
|
25
|
-
return current;
|
|
12
|
+
let current = class {};
|
|
13
|
+
for (const trait of traits) current = trait.factory(current);
|
|
14
|
+
for (const trait of traits) current[trait.symbol] = true;
|
|
15
|
+
return current;
|
|
26
16
|
}
|
|
27
17
|
function WithDerivations(base, ...traits) {
|
|
28
|
-
|
|
18
|
+
return Derive(Trait(() => base), ...traits);
|
|
29
19
|
}
|
|
30
20
|
const Trait = (factory) => {
|
|
31
|
-
|
|
32
|
-
|
|
21
|
+
return {
|
|
22
|
+
factory,
|
|
23
|
+
superTraits: [],
|
|
24
|
+
symbol: Symbol()
|
|
25
|
+
};
|
|
33
26
|
};
|
|
34
|
-
exports.Trait = Trait;
|
|
35
27
|
function implementsTrait(instance, trait) {
|
|
36
|
-
|
|
28
|
+
return instance.constructor[trait.symbol] === true;
|
|
37
29
|
}
|
|
38
|
-
const WithProps = () =>
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
return Intermediate;
|
|
30
|
+
const WithProps = () => Trait((base) => {
|
|
31
|
+
class Intermediate extends base {}
|
|
32
|
+
return Intermediate;
|
|
42
33
|
});
|
|
34
|
+
|
|
35
|
+
//#endregion
|
|
36
|
+
exports.Derive = Derive;
|
|
37
|
+
exports.Subtrait = Subtrait;
|
|
38
|
+
exports.Trait = Trait;
|
|
39
|
+
exports.WithDerivations = WithDerivations;
|
|
43
40
|
exports.WithProps = WithProps;
|
|
44
|
-
|
|
41
|
+
exports.implementsTrait = implementsTrait;
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
//#region src/index.ts
|
|
2
|
+
function Subtrait(superTraits, factory) {
|
|
3
|
+
return {
|
|
4
|
+
factory,
|
|
5
|
+
superTraits,
|
|
6
|
+
symbol: Symbol()
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
function Derive(...traits) {
|
|
10
|
+
let current = class {};
|
|
11
|
+
for (const trait of traits) current = trait.factory(current);
|
|
12
|
+
for (const trait of traits) current[trait.symbol] = true;
|
|
13
|
+
return current;
|
|
14
|
+
}
|
|
15
|
+
function WithDerivations(base, ...traits) {
|
|
16
|
+
return Derive(Trait(() => base), ...traits);
|
|
17
|
+
}
|
|
18
|
+
const Trait = (factory) => {
|
|
19
|
+
return {
|
|
20
|
+
factory,
|
|
21
|
+
superTraits: [],
|
|
22
|
+
symbol: Symbol()
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
function implementsTrait(instance, trait) {
|
|
26
|
+
return instance.constructor[trait.symbol] === true;
|
|
27
|
+
}
|
|
28
|
+
const WithProps = () => Trait((base) => {
|
|
29
|
+
class Intermediate extends base {}
|
|
30
|
+
return Intermediate;
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
//#endregion
|
|
34
|
+
export { Derive, Subtrait, Trait, WithDerivations, WithProps, implementsTrait };
|
package/package.json
CHANGED
|
@@ -1,18 +1,30 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ddd-ts/traits",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"main": "dist/index.js",
|
|
3
|
+
"version": "0.0.38",
|
|
5
4
|
"types": "dist/index.d.ts",
|
|
6
5
|
"license": "MIT",
|
|
7
6
|
"repository": {
|
|
8
7
|
"url": "git+https://github.com/ddd-ts/monorepo"
|
|
9
8
|
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist"
|
|
11
|
+
],
|
|
12
|
+
"devDependencies": {
|
|
13
|
+
"@ddd-ts/tools": "0.0.38",
|
|
14
|
+
"@types/jest": "^29.5.12",
|
|
15
|
+
"@types/node": "^22.14.1"
|
|
16
|
+
},
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"import": "./dist/index.mjs",
|
|
20
|
+
"require": "./dist/index.js"
|
|
21
|
+
},
|
|
22
|
+
"./package.json": "./package.json"
|
|
23
|
+
},
|
|
24
|
+
"main": "./dist/index.js",
|
|
25
|
+
"module": "./dist/index.mjs",
|
|
10
26
|
"scripts": {
|
|
11
|
-
"build": "
|
|
27
|
+
"build": "tsdown --config node_modules/@ddd-ts/tools/tsdown.config.js",
|
|
12
28
|
"test": "jest --config node_modules/@ddd-ts/tools/jest.config.js"
|
|
13
|
-
},
|
|
14
|
-
"devDependencies": {
|
|
15
|
-
"@ddd-ts/tools": "0.0.36",
|
|
16
|
-
"@types/jest": "^29.5.12"
|
|
17
29
|
}
|
|
18
|
-
}
|
|
30
|
+
}
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AA4FA,4BAcC;AAaD,wBAeC;AAED,0CAQC;AAaD,0CAKC;AAtED,SAAgB,QAAQ,CAOtB,WAAwB,EAAE,OAAgB;IAC1C,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;IACxB,OAAO;QACL,OAAO;QACP,WAAW;QACX,MAAM;KACP,CAAC;AACJ,CAAC;AAaD,SAAgB,MAAM,CACpB,GAAG,MAAS;IAIZ,IAAI,OAAO,GAAgB;KAAQ,CAAC;IACpC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACnC,CAAC;IAED,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC1B,OAAe,CAAE,KAAa,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC;IACjD,CAAC;IAED,OAAO,OAAc,CAAC;AACxB,CAAC;AAED,SAAgB,eAAe,CAG7B,IAAO,EAAE,GAAG,MAAS;IACrB,OAAO,MAAM,CACX,IAAA,aAAK,EAAC,GAAG,EAAE,CAAC,IAAI,CAAC,EACjB,GAAG,MAAM,CACV,CAAC;AACJ,CAAC;AAEM,MAAM,KAAK,GAAG,CAKnB,OAAU,EACV,EAAE;IACF,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;IACxB,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,EAAa,EAAE,MAAM,EAAE,CAAC;AACzD,CAAC,CAAC;AATW,QAAA,KAAK,SAShB;AAEF,SAAgB,eAAe,CAC7B,QAAW,EACX,KAAQ;IAER,OAAQ,QAAgB,CAAC,WAAW,CAAE,KAAa,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC;AACvE,CAAC;AAqBM,MAAM,SAAS,GAAG,GAAkC,EAAE,CAC3D,IAAA,aAAK,EAAC,CAAC,IAAI,EAAE,EAAE;IACb,MAAM,YAAa,SAAQ,IAAI;KAAG;IAQlC,OAAO,YAAuC,CAAC;AACjD,CAAC,CAAC,CAAC;AAXQ,QAAA,SAAS,aAWjB","sourcesContent":["export type Constructor<in Props = any, Result extends {} = {}> = new (\n props: Props,\n) => Result;\nexport type AbstractConstructor<\n Props = any,\n Result extends {} = {},\n> = abstract new (props: Props) => Result;\n\nexport type Trait<\n Factory extends <Base extends AbstractConstructor>(\n base: Base,\n ) => AbstractConstructor = any,\n> = {\n factory: Factory;\n superTraits: readonly Trait<any>[];\n};\n\ntype Explode<T> = { [P in keyof T]: T[P] };\n\nexport type UnionToIntersection<U> = (\n U extends any\n ? (k: U) => void\n : never\n) extends (k: infer I) => void\n ? I\n : never;\n\ntype MergeStaticSide<T extends readonly Trait[]> = UnionToIntersection<\n Explode<ReturnType<[...T][number][\"factory\"]>>\n>;\n\nexport type MergeInstanceSide<T extends readonly Trait[]> = T extends []\n ? {}\n : T extends never[]\n ? {}\n : UnionToIntersection<InstanceType<ReturnType<[...T][number][\"factory\"]>>>;\n\nexport type MergeParameter<T extends readonly Trait[]> = T extends []\n ? {}\n : T extends never[]\n ? {}\n : ConstructorParameters<ReturnType<[...T][number][\"factory\"]>>[0] extends {}\n ? UnionToIntersection<\n ConstructorParameters<ReturnType<[...T][number][\"factory\"]>>[0]\n >\n : ConstructorParameters<ReturnType<[...T][number][\"factory\"]>>[0];\n\nexport type ApplyTraits<T extends readonly Trait[]> = {\n new (param: MergeParameter<T>): MergeInstanceSide<T>;\n} & MergeStaticSide<T>;\n\nexport type CheckTraitRequirements<Traits extends readonly Trait[]> =\n CheckTraitRequirementsInternal<[], Traits>;\n\ntype CheckTraitRequirementsInternal<\n AppliedTraits extends readonly Trait[],\n RemainingTraits extends readonly Trait[],\n> = RemainingTraits extends readonly [\n infer ApplyingTrait extends Trait,\n ...infer Rest extends Trait[],\n]\n ? MergeParameter<AppliedTraits> extends MergeParameter<\n ApplyingTrait[\"superTraits\"]\n >\n ? MergeInstanceSide<AppliedTraits> extends MergeInstanceSide<\n ApplyingTrait[\"superTraits\"]\n >\n ? CheckTraitRequirementsInternal<[...AppliedTraits, ApplyingTrait], Rest>\n : {\n error: \"Instance mismatch\";\n check: \"MergeInstanceSide<AppliedTraits> extends MergeInstanceSide<ApplyingTrait['superTraits']>\";\n left: MergeInstanceSide<AppliedTraits>;\n right: MergeInstanceSide<ApplyingTrait[\"superTraits\"]>;\n result: MergeInstanceSide<AppliedTraits> extends MergeInstanceSide<\n ApplyingTrait[\"superTraits\"]\n >\n ? true\n : false;\n }\n : {\n error: \"Parameter mismatch\";\n check: \"MergeParameter<AppliedTraits> extends MergeParameter<[ApplyingTrait]>\";\n left: MergeParameter<AppliedTraits>;\n right: MergeParameter<[ApplyingTrait]>;\n result: MergeParameter<AppliedTraits> extends MergeParameter<\n [ApplyingTrait]\n >\n ? true\n : false;\n }\n : \"success\";\n\nexport function Subtrait<\n const SuperTraits extends readonly Trait[],\n Applied extends ApplyTraits<SuperTraits>,\n const Factory extends (\n base: Applied,\n props: ConstructorParameters<Applied>[0],\n ) => AbstractConstructor,\n>(superTraits: SuperTraits, factory: Factory) {\n const symbol = Symbol();\n return {\n factory,\n superTraits,\n symbol,\n };\n}\n\nexport type Props<T extends { __traits_props__: any } | Trait | Trait[]> =\n T extends {\n __traits_props__: any;\n }\n ? T[\"__traits_props__\"]\n : T extends Trait\n ? MergeParameter<[T]>\n : T extends Trait[]\n ? MergeParameter<T>\n : never;\n\nexport function Derive<R extends Trait[], C extends CheckTraitRequirements<R>>(\n ...traits: R\n): C extends \"success\"\n ? ApplyTraits<R> & { __traits__: R; __traits_props__: MergeParameter<R> }\n : C {\n let current: Constructor = class {};\n for (const trait of traits) {\n current = trait.factory(current);\n }\n\n for (const trait of traits) {\n (current as any)[(trait as any).symbol] = true;\n }\n\n return current as any;\n}\n\nexport function WithDerivations<\n B extends AbstractConstructor<any>,\n R extends Trait[],\n>(base: B, ...traits: R) {\n return Derive(\n Trait(() => base),\n ...traits,\n );\n}\n\nexport const Trait = <\n T extends (\n base: AbstractConstructor<{}, {}>,\n ) => AbstractConstructor<any, any>,\n>(\n factory: T,\n) => {\n const symbol = Symbol();\n return { factory, superTraits: [] as Trait[], symbol };\n};\n\nexport function implementsTrait<I extends InstanceType<any>, T extends Trait>(\n instance: I,\n trait: T,\n): instance is ImplementsTrait<T> {\n return (instance as any).constructor[(trait as any).symbol] === true;\n}\n\nexport type ConstructorWithTrait<T extends Trait> = Omit<\n ReturnType<T[\"factory\"]>,\n \"\"\n> &\n (new (\n ...args: any[]\n ) => ImplementsTrait<T>);\n\nexport type HasTrait<T extends Trait | ((...args: any[]) => Trait)> =\n T extends (...args: any[]) => Trait\n ? HasTrait<ReturnType<T>>\n : T extends Trait\n ? ConstructorWithTrait<T>\n : never;\n\nexport type ImplementsTrait<T extends Trait> = InstanceType<\n ReturnType<T[\"factory\"]>\n>;\n\nexport const WithProps = <P extends Record<string, any>>() =>\n Trait((base) => {\n class Intermediate extends base {}\n type I = typeof Intermediate extends new (\n ...args: infer A\n ) => infer T\n ? new (\n ...args: A\n ) => T & P\n : never;\n return Intermediate as typeof Intermediate & I;\n });\n"]}
|
package/dist/index.spec.js
DELETED
|
@@ -1,426 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const _1 = require(".");
|
|
4
|
-
describe("Traits", () => {
|
|
5
|
-
const Swim = (0, _1.Trait)((base) => class Swim extends base {
|
|
6
|
-
swim() {
|
|
7
|
-
return 1;
|
|
8
|
-
}
|
|
9
|
-
});
|
|
10
|
-
const Walk = (0, _1.Trait)((base) => class extends base {
|
|
11
|
-
walk() {
|
|
12
|
-
return 1;
|
|
13
|
-
}
|
|
14
|
-
});
|
|
15
|
-
it("derives a trait", () => {
|
|
16
|
-
class Fish extends (0, _1.Derive)(Swim) {
|
|
17
|
-
do() {
|
|
18
|
-
// @ts-expect-error should be strictly typed
|
|
19
|
-
this.test();
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
const fish = new Fish({});
|
|
23
|
-
expect(fish.swim()).toBe(1);
|
|
24
|
-
});
|
|
25
|
-
it("overloads a trait method", () => {
|
|
26
|
-
class Dog extends (0, _1.Derive)(Swim) {
|
|
27
|
-
swim() {
|
|
28
|
-
return super.swim() * 0.2;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
const dog = new Dog({});
|
|
32
|
-
expect(dog.swim()).toBe(0.2);
|
|
33
|
-
});
|
|
34
|
-
it("derives multiple traits", () => {
|
|
35
|
-
class Dog extends (0, _1.Derive)(Swim, Walk) {
|
|
36
|
-
}
|
|
37
|
-
const dog = new Dog({});
|
|
38
|
-
expect(dog.swim()).toBe(1);
|
|
39
|
-
expect(dog.walk()).toBe(1);
|
|
40
|
-
});
|
|
41
|
-
const Run = (0, _1.Trait)((base) => class extends base {
|
|
42
|
-
speed;
|
|
43
|
-
constructor(props) {
|
|
44
|
-
super(props);
|
|
45
|
-
this.speed = props.speed;
|
|
46
|
-
}
|
|
47
|
-
run() {
|
|
48
|
-
return 2 * this.speed;
|
|
49
|
-
}
|
|
50
|
-
});
|
|
51
|
-
it("derives a trait with a constructor", () => {
|
|
52
|
-
class Athlete extends (0, _1.Derive)(Run) {
|
|
53
|
-
constructor() {
|
|
54
|
-
super({ speed: 10 });
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
class ErrorAthlete extends (0, _1.Derive)(Run) {
|
|
58
|
-
constructor() {
|
|
59
|
-
// @ts-expect-error ensures the super constructor is called with the right props
|
|
60
|
-
super({});
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
const walker = new Athlete();
|
|
64
|
-
expect(walker.run()).toBe(20);
|
|
65
|
-
});
|
|
66
|
-
const Jump = (0, _1.Trait)((base) => class extends base {
|
|
67
|
-
agility;
|
|
68
|
-
constructor(props) {
|
|
69
|
-
super(props);
|
|
70
|
-
this.agility = props.agility;
|
|
71
|
-
}
|
|
72
|
-
jump() {
|
|
73
|
-
return 1;
|
|
74
|
-
}
|
|
75
|
-
});
|
|
76
|
-
it("derives multiple trait with a constructor", () => {
|
|
77
|
-
class Athlete extends (0, _1.Derive)(Run, Jump) {
|
|
78
|
-
constructor() {
|
|
79
|
-
super({ speed: 10, agility: 10 });
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
const walker = new Athlete();
|
|
83
|
-
expect(walker.run()).toBe(20);
|
|
84
|
-
});
|
|
85
|
-
it("asserts an instance implements a trait", () => {
|
|
86
|
-
const Unused = (0, _1.Trait)((base) => class extends base {
|
|
87
|
-
constructor(props) {
|
|
88
|
-
super(props);
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
|
-
class Athlete extends (0, _1.Derive)(Run, Jump) {
|
|
92
|
-
constructor() {
|
|
93
|
-
super({ speed: 10, agility: 10 });
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
const athlete = new Athlete();
|
|
97
|
-
expect(athlete instanceof Athlete).toBe(true);
|
|
98
|
-
expect((0, _1.implementsTrait)(athlete, Run)).toBe(true);
|
|
99
|
-
expect((0, _1.implementsTrait)(athlete, Jump)).toBe(true);
|
|
100
|
-
expect((0, _1.implementsTrait)(athlete, Unused)).toBe(false);
|
|
101
|
-
const unknown = athlete;
|
|
102
|
-
if ((0, _1.implementsTrait)(unknown, Run) && (0, _1.implementsTrait)(unknown, Jump)) {
|
|
103
|
-
// if type error, ensure the type guard works
|
|
104
|
-
unknown.run();
|
|
105
|
-
unknown.jump();
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
it("allows generic traits", () => {
|
|
109
|
-
const Eat = () => (0, _1.Trait)((base) => class extends base {
|
|
110
|
-
eat(_e) { }
|
|
111
|
-
});
|
|
112
|
-
class Animal extends (0, _1.Derive)(Eat()) {
|
|
113
|
-
do() {
|
|
114
|
-
this.eat("a");
|
|
115
|
-
// @ts-expect-error should not allow to eat a number
|
|
116
|
-
this.eat(1);
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
});
|
|
120
|
-
it("allows to easily access prop types", () => {
|
|
121
|
-
const WithProperties = () => (0, _1.Trait)((base) => class extends base {
|
|
122
|
-
a;
|
|
123
|
-
b;
|
|
124
|
-
c;
|
|
125
|
-
constructor(props) {
|
|
126
|
-
super(props);
|
|
127
|
-
this.a = props.a;
|
|
128
|
-
this.b = props.b;
|
|
129
|
-
this.c = props.c;
|
|
130
|
-
}
|
|
131
|
-
});
|
|
132
|
-
class Thing extends (0, _1.Derive)(WithProperties()) {
|
|
133
|
-
constructor(props) {
|
|
134
|
-
super(props);
|
|
135
|
-
}
|
|
136
|
-
do() {
|
|
137
|
-
const a = this.a;
|
|
138
|
-
const b = this.b;
|
|
139
|
-
const c = this.c;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
});
|
|
143
|
-
it("allows a trait to construct the base class", () => {
|
|
144
|
-
const WithProperties = () => (0, _1.Trait)((base) => class extends base {
|
|
145
|
-
a;
|
|
146
|
-
b;
|
|
147
|
-
c;
|
|
148
|
-
constructor(props) {
|
|
149
|
-
super(props);
|
|
150
|
-
this.a = props.a;
|
|
151
|
-
this.b = props.b;
|
|
152
|
-
this.c = props.c;
|
|
153
|
-
}
|
|
154
|
-
static new(props) {
|
|
155
|
-
return new this({ ...props });
|
|
156
|
-
}
|
|
157
|
-
});
|
|
158
|
-
class Thing extends (0, _1.Derive)(WithProperties()) {
|
|
159
|
-
constructor(props) {
|
|
160
|
-
super(props);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
Thing.new({ a: "a", b: true, c: 1, d: null });
|
|
164
|
-
});
|
|
165
|
-
describe("Subtraits", () => {
|
|
166
|
-
it("allows to specify supertraits", () => {
|
|
167
|
-
const Walk = (0, _1.Trait)((base) => class Walk extends base {
|
|
168
|
-
walk() { }
|
|
169
|
-
});
|
|
170
|
-
const Run = (0, _1.Subtrait)([Walk], // supertrait of subtrait defined here
|
|
171
|
-
(base) => class Run extends base {
|
|
172
|
-
run() {
|
|
173
|
-
this.walk();
|
|
174
|
-
this.walk();
|
|
175
|
-
this.walk();
|
|
176
|
-
}
|
|
177
|
-
});
|
|
178
|
-
// @ts-expect-error should not allow to create a runner without a walker
|
|
179
|
-
class ErrorAthlete extends (0, _1.Derive)(Run) {
|
|
180
|
-
}
|
|
181
|
-
// @ts-expect-error ordering matters: an athlete is a Runner because it is a walker
|
|
182
|
-
class ErrorAthlete2 extends (0, _1.Derive)(Run, Walk) {
|
|
183
|
-
}
|
|
184
|
-
class Athlete extends (0, _1.Derive)(Walk, Run) {
|
|
185
|
-
do() {
|
|
186
|
-
this.walk();
|
|
187
|
-
this.run();
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
});
|
|
191
|
-
it("allows to specify supertraits with props", () => {
|
|
192
|
-
const Walk = (0, _1.Trait)((base) => class extends base {
|
|
193
|
-
walk() {
|
|
194
|
-
return 2;
|
|
195
|
-
}
|
|
196
|
-
});
|
|
197
|
-
const Run = (0, _1.Subtrait)([Walk], // supertrait of subtrait defined here
|
|
198
|
-
(base) => class extends base {
|
|
199
|
-
speed;
|
|
200
|
-
constructor(props) {
|
|
201
|
-
super({});
|
|
202
|
-
this.speed = props.speed;
|
|
203
|
-
}
|
|
204
|
-
run() {
|
|
205
|
-
return this.walk() * this.speed;
|
|
206
|
-
}
|
|
207
|
-
});
|
|
208
|
-
class Athlete extends (0, _1.Derive)(Walk, Run) {
|
|
209
|
-
constructor() {
|
|
210
|
-
super({ speed: 10 });
|
|
211
|
-
}
|
|
212
|
-
start() {
|
|
213
|
-
return this.walk() + this.run();
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
const athlete = new Athlete();
|
|
217
|
-
expect(athlete.start()).toBe(22);
|
|
218
|
-
});
|
|
219
|
-
it("ensures supertraits props are forwarded", () => {
|
|
220
|
-
const Walk = (0, _1.Trait)((base) => class extends base {
|
|
221
|
-
speed;
|
|
222
|
-
constructor(props) {
|
|
223
|
-
super(props);
|
|
224
|
-
this.speed = props.speed;
|
|
225
|
-
}
|
|
226
|
-
walk() {
|
|
227
|
-
return this.speed * 0.1;
|
|
228
|
-
}
|
|
229
|
-
});
|
|
230
|
-
const Run = (0, _1.Subtrait)([Walk], // supertrait of subtrait defined here
|
|
231
|
-
(base, Props) => class extends base {
|
|
232
|
-
weigth;
|
|
233
|
-
constructor(props) {
|
|
234
|
-
super(props);
|
|
235
|
-
this.weigth = props.weigth;
|
|
236
|
-
}
|
|
237
|
-
run() {
|
|
238
|
-
return this.walk() * 10 + this.weigth;
|
|
239
|
-
}
|
|
240
|
-
});
|
|
241
|
-
class Athlete extends (0, _1.Derive)(Walk, Run) {
|
|
242
|
-
start() {
|
|
243
|
-
return this.walk() + this.run();
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
// @ts-expect-error missing subtrait props
|
|
247
|
-
new Athlete({ speed: 10 });
|
|
248
|
-
// @ts-expect-error missing supertrait props
|
|
249
|
-
new Athlete({ weigth: 10 });
|
|
250
|
-
const athlete = new Athlete({ speed: 10, weigth: 10 });
|
|
251
|
-
expect(athlete.start()).toBe(21);
|
|
252
|
-
});
|
|
253
|
-
it("ensures supertraits props are forwarded with multiple subtraits", () => {
|
|
254
|
-
const Walk = (0, _1.Trait)((base) => class Walk extends base {
|
|
255
|
-
speed;
|
|
256
|
-
constructor(props) {
|
|
257
|
-
super({});
|
|
258
|
-
this.speed = props.speed;
|
|
259
|
-
}
|
|
260
|
-
walk() {
|
|
261
|
-
return this.speed * 0.1;
|
|
262
|
-
}
|
|
263
|
-
});
|
|
264
|
-
const Fly = (0, _1.Trait)((base) => class Fly extends base {
|
|
265
|
-
wings;
|
|
266
|
-
constructor(props) {
|
|
267
|
-
super({});
|
|
268
|
-
this.wings = props.wings;
|
|
269
|
-
}
|
|
270
|
-
fly() {
|
|
271
|
-
// @ts-expect-error wings is a number
|
|
272
|
-
const s = this.wings;
|
|
273
|
-
return this.wings;
|
|
274
|
-
}
|
|
275
|
-
});
|
|
276
|
-
const Land = (0, _1.Subtrait)([Walk, Fly], // supertrait of subtrait defined here
|
|
277
|
-
(base, Props) => class Land extends base {
|
|
278
|
-
weigth;
|
|
279
|
-
constructor(props) {
|
|
280
|
-
super(props);
|
|
281
|
-
this.weigth = props.weigth;
|
|
282
|
-
}
|
|
283
|
-
land() {
|
|
284
|
-
return this.walk() + this.fly() - this.weigth;
|
|
285
|
-
}
|
|
286
|
-
});
|
|
287
|
-
// @ts-expect-error Land requires Walk & Fly
|
|
288
|
-
(class extends (0, _1.Derive)(Land) {
|
|
289
|
-
});
|
|
290
|
-
// @ts-expect-error Land requires Walk & Fly
|
|
291
|
-
(class extends (0, _1.Derive)(Walk, Land) {
|
|
292
|
-
});
|
|
293
|
-
// @ts-expect-error Land requires Walk & Fly
|
|
294
|
-
(class extends (0, _1.Derive)(Fly, Land) {
|
|
295
|
-
});
|
|
296
|
-
// @ts-expect-error Land requires Walk & Fly in correct order
|
|
297
|
-
(class extends (0, _1.Derive)(Land, Walk, Fly) {
|
|
298
|
-
});
|
|
299
|
-
class Athlete extends (0, _1.Derive)(Walk, Fly, Land) {
|
|
300
|
-
}
|
|
301
|
-
// @ts-expect-error missing props
|
|
302
|
-
new Athlete({ speed: 10 });
|
|
303
|
-
// @ts-expect-error missing props
|
|
304
|
-
new Athlete({ wings: 10 });
|
|
305
|
-
// @ts-expect-error missing props
|
|
306
|
-
new Athlete({ weigth: 10 });
|
|
307
|
-
// @ts-expect-error missing props
|
|
308
|
-
new Athlete({ speed: 10, weigth: 10 });
|
|
309
|
-
// @ts-expect-error missing props
|
|
310
|
-
new Athlete({ speed: 10, wings: 10 });
|
|
311
|
-
// @ts-expect-error missing props
|
|
312
|
-
new Athlete({ weigth: 10, wings: 10 });
|
|
313
|
-
new Athlete({ speed: 10, weigth: 10, wings: 10 });
|
|
314
|
-
});
|
|
315
|
-
it("ensures a class can derive traits that dont depend on all other traits", () => {
|
|
316
|
-
const Walk = (0, _1.Trait)((base) => class Walk extends base {
|
|
317
|
-
speed;
|
|
318
|
-
constructor(props) {
|
|
319
|
-
super({});
|
|
320
|
-
this.speed = props.speed;
|
|
321
|
-
}
|
|
322
|
-
walk() {
|
|
323
|
-
return this.speed * 0.1;
|
|
324
|
-
}
|
|
325
|
-
});
|
|
326
|
-
const Fly = (0, _1.Trait)((base) => class Fly extends base {
|
|
327
|
-
wings;
|
|
328
|
-
constructor(props) {
|
|
329
|
-
super({});
|
|
330
|
-
this.wings = props.wings;
|
|
331
|
-
}
|
|
332
|
-
fly() {
|
|
333
|
-
// @ts-expect-error wings is a number
|
|
334
|
-
const s = this.wings;
|
|
335
|
-
return this.wings;
|
|
336
|
-
}
|
|
337
|
-
});
|
|
338
|
-
const Land = (0, _1.Subtrait)([Walk], // supertrait of subtrait defined here
|
|
339
|
-
(base, Props) => class Land extends base {
|
|
340
|
-
weigth;
|
|
341
|
-
constructor(props) {
|
|
342
|
-
super(props);
|
|
343
|
-
this.weigth = props.weigth;
|
|
344
|
-
}
|
|
345
|
-
land() {
|
|
346
|
-
return this.walk() - this.weigth;
|
|
347
|
-
}
|
|
348
|
-
static isLander() {
|
|
349
|
-
return true;
|
|
350
|
-
}
|
|
351
|
-
});
|
|
352
|
-
// @ts-expect-error Land requires Walk & Fly
|
|
353
|
-
(class extends (0, _1.Derive)(Land) {
|
|
354
|
-
});
|
|
355
|
-
// @ts-expect-error Land requires Walk
|
|
356
|
-
(class extends (0, _1.Derive)(Fly, Land) {
|
|
357
|
-
});
|
|
358
|
-
// @ts-expect-error Land requires Walk & Fly in correct order
|
|
359
|
-
(class extends (0, _1.Derive)(Land, Walk, Fly) {
|
|
360
|
-
});
|
|
361
|
-
// @ts-expect-error Land requires Walk & Fly in correct order
|
|
362
|
-
(class extends (0, _1.Derive)(Fly, Land, Walk) {
|
|
363
|
-
});
|
|
364
|
-
class Athlete extends (0, _1.Derive)(Walk, Fly, Land) {
|
|
365
|
-
}
|
|
366
|
-
// @ts-expect-error missing props
|
|
367
|
-
new Athlete({ speed: 10 });
|
|
368
|
-
// @ts-expect-error missing props
|
|
369
|
-
new Athlete({ wings: 10 });
|
|
370
|
-
// @ts-expect-error missing props
|
|
371
|
-
new Athlete({ weigth: 10 });
|
|
372
|
-
// @ts-expect-error missing props
|
|
373
|
-
new Athlete({ speed: 10, weigth: 10 });
|
|
374
|
-
// @ts-expect-error missing props
|
|
375
|
-
new Athlete({ speed: 10, wings: 10 });
|
|
376
|
-
// @ts-expect-error missing props
|
|
377
|
-
new Athlete({ weigth: 10, wings: 10 });
|
|
378
|
-
new Athlete({ speed: 10, weigth: 10, wings: 10 });
|
|
379
|
-
});
|
|
380
|
-
});
|
|
381
|
-
it("allow abstract traits", () => {
|
|
382
|
-
const SomeTrait = (0, _1.Trait)((base) => {
|
|
383
|
-
class I extends base {
|
|
384
|
-
}
|
|
385
|
-
return I;
|
|
386
|
-
});
|
|
387
|
-
const SomeSubTrait = (0, _1.Subtrait)([SomeTrait], (base, Props) => {
|
|
388
|
-
class I extends base {
|
|
389
|
-
constructor(props) {
|
|
390
|
-
super(props);
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
return I;
|
|
394
|
-
});
|
|
395
|
-
class Test extends (0, _1.Derive)(SomeTrait, SomeSubTrait) {
|
|
396
|
-
do() {
|
|
397
|
-
console.log("do");
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
new Test({ test: 2 });
|
|
401
|
-
// @ts-expect-error
|
|
402
|
-
new Test({ anything: 2 });
|
|
403
|
-
});
|
|
404
|
-
it("allow to derive from a base class", () => {
|
|
405
|
-
class Base {
|
|
406
|
-
params;
|
|
407
|
-
constructor(params) {
|
|
408
|
-
this.params = params;
|
|
409
|
-
}
|
|
410
|
-
}
|
|
411
|
-
const SomeTrait = (0, _1.Trait)((base) => {
|
|
412
|
-
class I extends base {
|
|
413
|
-
}
|
|
414
|
-
return I;
|
|
415
|
-
});
|
|
416
|
-
class Test extends (0, _1.WithDerivations)(Base, SomeTrait) {
|
|
417
|
-
do() {
|
|
418
|
-
console.log("do");
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
new Test({ a: "a" });
|
|
422
|
-
// @ts-expect-error
|
|
423
|
-
new Test(2);
|
|
424
|
-
});
|
|
425
|
-
});
|
|
426
|
-
//# sourceMappingURL=index.spec.js.map
|
package/dist/index.spec.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.spec.js","sourceRoot":"","sources":["../src/index.spec.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Constructor,\n Derive,\n Props,\n Subtrait,\n Trait,\n WithDerivations,\n implementsTrait,\n} from \".\";\n\ndescribe(\"Traits\", () => {\n const Swim = Trait(\n (base) =>\n class Swim extends base {\n swim() {\n return 1;\n }\n },\n );\n\n const Walk = Trait(\n (base) =>\n class extends base {\n walk() {\n return 1;\n }\n },\n );\n\n it(\"derives a trait\", () => {\n class Fish extends Derive(Swim) {\n do() {\n // @ts-expect-error should be strictly typed\n this.test();\n }\n }\n\n const fish = new Fish({});\n\n expect(fish.swim()).toBe(1);\n });\n\n it(\"overloads a trait method\", () => {\n class Dog extends Derive(Swim) {\n swim() {\n return super.swim() * 0.2;\n }\n }\n\n const dog = new Dog({});\n\n expect(dog.swim()).toBe(0.2);\n });\n\n it(\"derives multiple traits\", () => {\n class Dog extends Derive(Swim, Walk) {}\n\n const dog = new Dog({});\n\n expect(dog.swim()).toBe(1);\n expect(dog.walk()).toBe(1);\n });\n\n const Run = Trait(\n (base) =>\n class extends base {\n speed: number;\n constructor(props: { speed: number }) {\n super(props);\n this.speed = props.speed;\n }\n run() {\n return 2 * this.speed;\n }\n },\n );\n\n it(\"derives a trait with a constructor\", () => {\n class Athlete extends Derive(Run) {\n constructor() {\n super({ speed: 10 });\n }\n }\n\n class ErrorAthlete extends Derive(Run) {\n constructor() {\n // @ts-expect-error ensures the super constructor is called with the right props\n super({});\n }\n }\n\n const walker = new Athlete();\n\n expect(walker.run()).toBe(20);\n });\n\n const Jump = Trait(\n (base) =>\n class extends base {\n agility: number;\n constructor(props: { agility: number }) {\n super(props);\n this.agility = props.agility;\n }\n jump() {\n return 1;\n }\n },\n );\n\n it(\"derives multiple trait with a constructor\", () => {\n class Athlete extends Derive(Run, Jump) {\n constructor() {\n super({ speed: 10, agility: 10 });\n }\n }\n\n const walker = new Athlete();\n\n expect(walker.run()).toBe(20);\n });\n\n it(\"asserts an instance implements a trait\", () => {\n const Unused = Trait(\n (base) =>\n class extends base {\n constructor(props: { agility: number }) {\n super(props);\n }\n },\n );\n\n class Athlete extends Derive(Run, Jump) {\n constructor() {\n super({ speed: 10, agility: 10 });\n }\n }\n\n const athlete = new Athlete();\n\n expect(athlete instanceof Athlete).toBe(true);\n expect(implementsTrait(athlete, Run)).toBe(true);\n expect(implementsTrait(athlete, Jump)).toBe(true);\n expect(implementsTrait(athlete, Unused)).toBe(false);\n\n const unknown: unknown = athlete;\n if (implementsTrait(unknown, Run) && implementsTrait(unknown, Jump)) {\n // if type error, ensure the type guard works\n unknown.run();\n unknown.jump();\n }\n });\n\n it(\"allows generic traits\", () => {\n const Eat = <E>() =>\n Trait(\n (base) =>\n class extends base {\n eat(_e: E) {}\n },\n );\n\n class Animal extends Derive(Eat<string>()) {\n do() {\n this.eat(\"a\");\n // @ts-expect-error should not allow to eat a number\n this.eat(1);\n }\n }\n });\n\n it(\"allows to easily access prop types\", () => {\n const WithProperties = <T>() =>\n Trait(\n (base) =>\n class extends base {\n a: string;\n b: T;\n c: number;\n constructor(props: { a: string; b: T; c: number }) {\n super(props);\n this.a = props.a;\n this.b = props.b;\n this.c = props.c;\n }\n },\n );\n\n class Thing extends Derive(WithProperties<boolean>()) {\n constructor(props: Props<typeof Thing> & { d: null }) {\n super(props);\n }\n\n do() {\n const a: string = this.a;\n const b: boolean = this.b;\n const c: number = this.c;\n }\n }\n });\n\n it(\"allows a trait to construct the base class\", () => {\n const WithProperties = <T>() =>\n Trait(\n (base) =>\n class extends base {\n a: string;\n b: T;\n c: number;\n constructor(props: { a: string; b: T; c: number }) {\n super(props);\n this.a = props.a;\n this.b = props.b;\n this.c = props.c;\n }\n static new<T extends Constructor>(\n this: T,\n props: ConstructorParameters<T>[0],\n ) {\n return new this({ ...props }) as InstanceType<T>;\n }\n },\n );\n\n class Thing extends Derive(WithProperties<boolean>()) {\n constructor(props: Props<typeof Thing> & { d: null }) {\n super(props);\n }\n }\n\n Thing.new({ a: \"a\", b: true, c: 1, d: null });\n });\n\n describe(\"Subtraits\", () => {\n it(\"allows to specify supertraits\", () => {\n const Walk = Trait(\n (base) =>\n class Walk extends base {\n walk() {}\n },\n );\n\n const Run = Subtrait(\n [Walk], // supertrait of subtrait defined here\n (base) =>\n class Run extends base {\n run() {\n this.walk();\n this.walk();\n this.walk();\n }\n },\n );\n\n // @ts-expect-error should not allow to create a runner without a walker\n class ErrorAthlete extends Derive(Run) {}\n\n // @ts-expect-error ordering matters: an athlete is a Runner because it is a walker\n class ErrorAthlete2 extends Derive(Run, Walk) {}\n\n class Athlete extends Derive(Walk, Run) {\n do() {\n this.walk();\n this.run();\n }\n }\n });\n\n it(\"allows to specify supertraits with props\", () => {\n const Walk = Trait(\n (base) =>\n class extends base {\n walk() {\n return 2;\n }\n },\n );\n\n const Run = Subtrait(\n [Walk], // supertrait of subtrait defined here\n (base) =>\n class extends base {\n speed: number;\n constructor(props: { speed: number }) {\n super({});\n this.speed = props.speed;\n }\n run() {\n return this.walk() * this.speed;\n }\n },\n );\n\n class Athlete extends Derive(Walk, Run) {\n constructor() {\n super({ speed: 10 });\n }\n start() {\n return this.walk() + this.run();\n }\n }\n\n const athlete = new Athlete();\n\n expect(athlete.start()).toBe(22);\n });\n\n it(\"ensures supertraits props are forwarded\", () => {\n const Walk = Trait(\n (base) =>\n class extends base {\n speed: number;\n constructor(props: { speed: number }) {\n super(props);\n this.speed = props.speed;\n }\n walk() {\n return this.speed * 0.1;\n }\n },\n );\n\n const Run = Subtrait(\n [Walk], // supertrait of subtrait defined here\n (base, Props) =>\n class extends base {\n weigth: number;\n constructor(props: { weigth: number } & typeof Props) {\n super(props);\n this.weigth = props.weigth;\n }\n run() {\n return this.walk() * 10 + this.weigth;\n }\n },\n );\n\n class Athlete extends Derive(Walk, Run) {\n start() {\n return this.walk() + this.run();\n }\n }\n\n // @ts-expect-error missing subtrait props\n new Athlete({ speed: 10 });\n\n // @ts-expect-error missing supertrait props\n new Athlete({ weigth: 10 });\n\n const athlete = new Athlete({ speed: 10, weigth: 10 });\n\n expect(athlete.start()).toBe(21);\n });\n\n it(\"ensures supertraits props are forwarded with multiple subtraits\", () => {\n const Walk = Trait(\n (base) =>\n class Walk extends base {\n speed: number;\n constructor(props: { speed: number }) {\n super({});\n this.speed = props.speed;\n }\n walk() {\n return this.speed * 0.1;\n }\n },\n );\n\n const Fly = Trait(\n (base) =>\n class Fly extends base {\n wings: number;\n constructor(props: { wings: number }) {\n super({});\n this.wings = props.wings;\n }\n fly() {\n // @ts-expect-error wings is a number\n const s: string = this.wings;\n return this.wings;\n }\n },\n );\n\n const Land = Subtrait(\n [Walk, Fly], // supertrait of subtrait defined here\n (base, Props) =>\n class Land extends base {\n weigth: number;\n constructor(props: { weigth: number } & typeof Props) {\n super(props);\n this.weigth = props.weigth;\n }\n land() {\n return this.walk() + this.fly() - this.weigth;\n }\n },\n );\n\n // @ts-expect-error Land requires Walk & Fly\n (class extends Derive(Land) {});\n\n // @ts-expect-error Land requires Walk & Fly\n (class extends Derive(Walk, Land) {});\n\n // @ts-expect-error Land requires Walk & Fly\n (class extends Derive(Fly, Land) {});\n\n // @ts-expect-error Land requires Walk & Fly in correct order\n (class extends Derive(Land, Walk, Fly) {});\n\n class Athlete extends Derive(Walk, Fly, Land) {}\n\n // @ts-expect-error missing props\n new Athlete({ speed: 10 });\n // @ts-expect-error missing props\n new Athlete({ wings: 10 });\n // @ts-expect-error missing props\n new Athlete({ weigth: 10 });\n // @ts-expect-error missing props\n new Athlete({ speed: 10, weigth: 10 });\n // @ts-expect-error missing props\n new Athlete({ speed: 10, wings: 10 });\n // @ts-expect-error missing props\n new Athlete({ weigth: 10, wings: 10 });\n\n new Athlete({ speed: 10, weigth: 10, wings: 10 });\n });\n\n it(\"ensures a class can derive traits that dont depend on all other traits\", () => {\n const Walk = Trait(\n (base) =>\n class Walk extends base {\n speed: number;\n constructor(props: { speed: number }) {\n super({});\n this.speed = props.speed;\n }\n walk() {\n return this.speed * 0.1;\n }\n },\n );\n\n const Fly = Trait(\n (base) =>\n class Fly extends base {\n wings: number;\n constructor(props: { wings: number }) {\n super({});\n this.wings = props.wings;\n }\n fly() {\n // @ts-expect-error wings is a number\n const s: string = this.wings;\n return this.wings;\n }\n },\n );\n\n const Land = Subtrait(\n [Walk], // supertrait of subtrait defined here\n (base, Props) =>\n class Land extends base {\n weigth: number;\n constructor(props: { weigth: number } & typeof Props) {\n super(props);\n this.weigth = props.weigth;\n }\n land() {\n return this.walk() - this.weigth;\n }\n\n static isLander() {\n return true;\n }\n },\n );\n\n // @ts-expect-error Land requires Walk & Fly\n (class extends Derive(Land) {});\n\n // @ts-expect-error Land requires Walk\n (class extends Derive(Fly, Land) {});\n\n // @ts-expect-error Land requires Walk & Fly in correct order\n (class extends Derive(Land, Walk, Fly) {});\n // @ts-expect-error Land requires Walk & Fly in correct order\n (class extends Derive(Fly, Land, Walk) {});\n\n class Athlete extends Derive(Walk, Fly, Land) {}\n\n // @ts-expect-error missing props\n new Athlete({ speed: 10 });\n // @ts-expect-error missing props\n new Athlete({ wings: 10 });\n // @ts-expect-error missing props\n new Athlete({ weigth: 10 });\n // @ts-expect-error missing props\n new Athlete({ speed: 10, weigth: 10 });\n // @ts-expect-error missing props\n new Athlete({ speed: 10, wings: 10 });\n // @ts-expect-error missing props\n new Athlete({ weigth: 10, wings: 10 });\n\n new Athlete({ speed: 10, weigth: 10, wings: 10 });\n });\n });\n\n it(\"allow abstract traits\", () => {\n const SomeTrait = Trait((base) => {\n abstract class I extends base {\n abstract do(): void;\n }\n return I;\n });\n\n const SomeSubTrait = Subtrait([SomeTrait], (base, Props) => {\n abstract class I extends base {\n constructor(props: { test: 2 } & typeof Props) {\n super(props);\n }\n\n abstract do(): void;\n }\n return I;\n });\n\n class Test extends Derive(SomeTrait, SomeSubTrait) {\n do() {\n console.log(\"do\");\n }\n }\n\n new Test({ test: 2 });\n // @ts-expect-error\n new Test({ anything: 2 });\n });\n\n it(\"allow to derive from a base class\", () => {\n class Base {\n constructor(public params: { a: string }) {}\n }\n\n const SomeTrait = Trait((base) => {\n abstract class I extends base {\n abstract do(): void;\n }\n return I;\n });\n\n class Test extends WithDerivations(Base, SomeTrait) {\n do() {\n console.log(\"do\");\n }\n }\n\n new Test({ a: \"a\" });\n // @ts-expect-error\n new Test(2);\n });\n});\n"]}
|