New implementation tests
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
24
src/index.ts
24
src/index.ts
@@ -154,30 +154,6 @@ export function extendsAndExpresses<
|
|||||||
extend: C,
|
extend: C,
|
||||||
...traits: Traits
|
...traits: Traits
|
||||||
) {
|
) {
|
||||||
// Combine all static members of the traits
|
|
||||||
type AllStaticMembers = UnionToIntersection<TraitClass<Traits[number]>>
|
|
||||||
|
|
||||||
// Combine all instance members of the traits
|
|
||||||
type AllInstanceMembers = UnionToIntersection<TraitInstance<Traits[number]>>
|
|
||||||
|
|
||||||
// Extract common keys from all traits
|
|
||||||
type CommonKeys = keyof AllStaticMembers & keyof AllInstanceMembers
|
|
||||||
|
|
||||||
// Exclude common keys from the static members of the last trait
|
|
||||||
type StaticMembersWithoutCommon = Omit<AllStaticMembers, CommonKeys>
|
|
||||||
|
|
||||||
// Exclude common keys from the instance members of the last trait
|
|
||||||
type InstanceMembersWithoutCommon = Omit<AllInstanceMembers, CommonKeys>
|
|
||||||
|
|
||||||
// Combine the instance members of the base class and the last trait
|
|
||||||
type CombinedInstanceMembers = InstanceType<C> & InstanceMembersWithoutCommon
|
|
||||||
|
|
||||||
// Combine the static members of the base class and the last trait
|
|
||||||
type CombinedStaticMembers = StaticMembers<C> & StaticMembersWithoutCommon
|
|
||||||
|
|
||||||
// Combine the instance and static members
|
|
||||||
type CombinedMembers = CombinedInstanceMembers & CombinedStaticMembers
|
|
||||||
|
|
||||||
return traits.reduce(
|
return traits.reduce(
|
||||||
(previous, trait) => trait(previous),
|
(previous, trait) => trait(previous),
|
||||||
extend as Opaque<C, TraitApplierTag>,
|
extend as Opaque<C, TraitApplierTag>,
|
||||||
|
|||||||
106
src/tests.ts
106
src/tests.ts
@@ -1,5 +1,5 @@
|
|||||||
import { AbstractClass, Class, Simplify } from "type-fest"
|
import { AbstractClass } from "type-fest"
|
||||||
import { TraitInstance, expresses, extendsAndExpresses, trait } from "."
|
import { expresses, extendsAndExpresses, trait } from "."
|
||||||
|
|
||||||
|
|
||||||
const Identifiable = <ID>() =>
|
const Identifiable = <ID>() =>
|
||||||
@@ -71,56 +71,84 @@ console.log(user1)
|
|||||||
console.log(user1.equals(user1))
|
console.log(user1.equals(user1))
|
||||||
|
|
||||||
|
|
||||||
abstract class TestTrait1 {
|
abstract class Test1 {
|
||||||
abstract variable: number
|
declare static name: string
|
||||||
abstract member: {
|
abstract name: string
|
||||||
issou: string
|
|
||||||
}
|
declare createdAt: Date
|
||||||
|
declare readonly status: (
|
||||||
|
{ _tag: "awaitingPayment" } |
|
||||||
|
{ _tag: "active", activeSince: Date, expiresAt?: Date } |
|
||||||
|
{ _tag: "expired", expiredSince: Date }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class TestTrait2 {
|
class Test2 {
|
||||||
abstract lol: BigInt
|
declare readonly status: { _tag: "active", activeSince: Date, expiresAt?: Date }
|
||||||
abstract member: {
|
|
||||||
issou: "gneugneu",
|
|
||||||
adolf: string
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class Test3 {
|
||||||
type StaticMembers<C> = {
|
declare lol: 10n
|
||||||
[Key in keyof C as Key extends "prototype" ? never : Key]: C[Key]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
type CommonKeys<A, B> = Extract<keyof A, keyof B>
|
type CommonKeys<A, B> = Extract<keyof A, keyof B>
|
||||||
|
|
||||||
type Extend2<Self, Parent> = (
|
type Extend<T extends readonly any[]> = (
|
||||||
Pick<Self, CommonKeys<Self, Parent>> extends Pick<Parent, CommonKeys<Self, Parent>>
|
T extends [infer Super, infer Self, ...infer Rest]
|
||||||
? Omit<Parent, CommonKeys<Self, Parent>> & Self
|
? Pick<Self, CommonKeys<Self, Super>> extends Pick<Super, CommonKeys<Self, Super>>
|
||||||
: never
|
? Extend<[
|
||||||
)
|
Omit<Super, CommonKeys<Self, Super>> & Self,
|
||||||
|
...Rest,
|
||||||
type ExtendN<Classes extends any[]> = (
|
]>
|
||||||
Classes extends [infer Parent, infer Self, ...infer Rest]
|
: never
|
||||||
? Extend2<Self, Parent> & ExtendN<Rest>
|
: T extends [infer Self]
|
||||||
: Classes extends [infer Self, ...infer Others]
|
|
||||||
? Self
|
? Self
|
||||||
: "Empty array"
|
: "Empty array"
|
||||||
)
|
)
|
||||||
|
|
||||||
// type ExtendClass<
|
type ClassesInstances<Classes extends readonly any[]> = (
|
||||||
// Self extends AbstractClass<any>,
|
Classes extends [infer Class, ...infer Rest]
|
||||||
// Parent extends AbstractClass<any>,
|
? Class extends AbstractClass<any>
|
||||||
// > = (
|
? [InstanceType<Class>, ...ClassesInstances<Rest>]
|
||||||
|
: never
|
||||||
|
: []
|
||||||
|
)
|
||||||
|
|
||||||
// )
|
type StaticMembers<Class extends AbstractClass<any>> = (
|
||||||
|
Omit<Class, "prototype">
|
||||||
|
)
|
||||||
|
|
||||||
type Test = Simplify<StaticMembers<typeof TestTrait2>>
|
type ClassesStaticMembers<Classes extends readonly any[]> = (
|
||||||
type MixedStaticTestTraits = ExtendN<[
|
Classes extends [infer Class, ...infer Rest]
|
||||||
StaticMembers<typeof TestTrait2>,
|
? Class extends AbstractClass<any>
|
||||||
StaticMembers<typeof TestTrait1>,
|
? [StaticMembers<Class>, ...ClassesStaticMembers<Rest>]
|
||||||
|
: never
|
||||||
|
: []
|
||||||
|
)
|
||||||
|
|
||||||
|
type ExtendClasses<Classes extends readonly AbstractClass<any>[]> = (
|
||||||
|
AbstractClass<
|
||||||
|
Extend<ClassesInstances<Classes>>
|
||||||
|
> &
|
||||||
|
Extend<ClassesStaticMembers<Classes>>
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
type MixedTestProto = ExtendClasses<[
|
||||||
|
typeof Test1,
|
||||||
|
typeof Test2,
|
||||||
|
typeof Test3,
|
||||||
]>
|
]>
|
||||||
|
|
||||||
type MixedTestTraitsProto = Class<
|
declare const MixedTestProto: MixedTestProto
|
||||||
Extend2<TestTrait2, TestTrait1>,
|
|
||||||
any[]
|
class MixedTest extends MixedTestProto {}
|
||||||
> & Extend2<StaticMembers<typeof TestTrait2>, StaticMembers<typeof TestTrait1>>
|
|
||||||
|
MixedTest.prototype
|
||||||
|
new MixedTest().name
|
||||||
|
|
||||||
|
// type MixedTestTraitsProto = Class<
|
||||||
|
// Extend2<TestTrait2, TestTrait1>,
|
||||||
|
// any[]
|
||||||
|
// > & Extend2<StaticMembers<typeof TestTrait2>, StaticMembers<typeof TestTrait1>>
|
||||||
|
|||||||
Reference in New Issue
Block a user