New implementation tests
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
Julien Valverdé
2024-01-27 02:20:56 +01:00
parent 69ecd95cbb
commit e5fbee56ed
2 changed files with 67 additions and 63 deletions

View File

@@ -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>,

View File

@@ -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>>