This commit is contained in:
76
src/trait.ts
76
src/trait.ts
@@ -3,30 +3,30 @@ import { AbstractClass, Class, Opaque } from "type-fest"
|
||||
import { StaticMembers } from "./util"
|
||||
|
||||
|
||||
// type AddAbstractMembersToImpl<
|
||||
// Impl extends Class<object, []>,
|
||||
// AbstractMembers extends object,
|
||||
// > = (
|
||||
// Class<
|
||||
// InstanceType<Impl> & AbstractMembers,
|
||||
// ConstructorParameters<Impl>
|
||||
// > &
|
||||
// StaticMembers<Impl>
|
||||
// )
|
||||
type AddAbstractToImplClass<
|
||||
Impl extends Class<object, []>,
|
||||
Abstract extends object,
|
||||
> = (
|
||||
Class<
|
||||
InstanceType<Impl> & Abstract,
|
||||
ConstructorParameters<Impl>
|
||||
> &
|
||||
StaticMembers<Impl>
|
||||
)
|
||||
|
||||
type RemoveAbstractMembersFromImplInstance<
|
||||
type RemoveAbstractFromImplInstance<
|
||||
ImplInstanceWithAbstractMembers extends AbstractMembers,
|
||||
AbstractMembers extends object,
|
||||
> = (
|
||||
Omit<ImplInstanceWithAbstractMembers, keyof AbstractMembers>
|
||||
)
|
||||
|
||||
type RemoveAbstractMembersFromImplClass<
|
||||
type RemoveAbstractFromImplClass<
|
||||
ImplWithAbstractMembers extends Class<AbstractMembers, []>,
|
||||
AbstractMembers extends object,
|
||||
> = (
|
||||
Class<
|
||||
RemoveAbstractMembersFromImplInstance<
|
||||
RemoveAbstractFromImplInstance<
|
||||
InstanceType<ImplWithAbstractMembers>,
|
||||
AbstractMembers
|
||||
>,
|
||||
@@ -40,13 +40,13 @@ type RemoveAbstractMembersFromImplClass<
|
||||
export type TraitTag = "@thilawyn/traitify-ts/Trait"
|
||||
|
||||
export type Trait<
|
||||
AbstractMembers extends object,
|
||||
ImplWithAbstractMembers extends Class<AbstractMembers, []>,
|
||||
Abstract extends object,
|
||||
Impl extends Class<object, []>,
|
||||
> = (
|
||||
Opaque<{
|
||||
readonly apply: TraitApplier<
|
||||
AbstractMembers,
|
||||
ImplWithAbstractMembers
|
||||
Abstract,
|
||||
AddAbstractToImplClass<Impl, Abstract>
|
||||
>
|
||||
}, TraitTag>
|
||||
)
|
||||
@@ -62,11 +62,8 @@ export interface TraitAbstractMembersFn extends Fn {
|
||||
}
|
||||
|
||||
export type TraitImplClass<T> = (
|
||||
T extends Trait<infer AbstractMembers, infer ImplWithAbstractMembers>
|
||||
? RemoveAbstractMembersFromImplClass<
|
||||
ImplWithAbstractMembers,
|
||||
AbstractMembers
|
||||
>
|
||||
T extends Trait<any, infer Impl>
|
||||
? Impl
|
||||
: never
|
||||
)
|
||||
|
||||
@@ -75,11 +72,8 @@ export interface TraitImplClassFn extends Fn {
|
||||
}
|
||||
|
||||
export type TraitImplInstance<T> = (
|
||||
T extends Trait<infer AbstractMembers, infer ImplWithAbstractMembers>
|
||||
? RemoveAbstractMembersFromImplInstance<
|
||||
InstanceType<ImplWithAbstractMembers>,
|
||||
AbstractMembers
|
||||
>
|
||||
T extends Trait<any, infer Impl>
|
||||
? InstanceType<Impl>
|
||||
: never
|
||||
)
|
||||
|
||||
@@ -88,8 +82,8 @@ export interface TraitImplInstanceFn extends Fn {
|
||||
}
|
||||
|
||||
export type TraitClass<T> = (
|
||||
T extends Trait<any, infer ImplWithAbstractMembers>
|
||||
? ImplWithAbstractMembers
|
||||
T extends Trait<infer Abstract, infer Impl>
|
||||
? AddAbstractToImplClass<Impl, Abstract>
|
||||
: never
|
||||
)
|
||||
|
||||
@@ -98,8 +92,10 @@ export interface TraitClassFn extends Fn {
|
||||
}
|
||||
|
||||
export type TraitInstance<T> = (
|
||||
T extends Trait<any, infer ImplWithAbstractMembers>
|
||||
? InstanceType<ImplWithAbstractMembers>
|
||||
T extends Trait<infer Abstract, infer Impl>
|
||||
? InstanceType<
|
||||
AddAbstractToImplClass<Impl, Abstract>
|
||||
>
|
||||
: never
|
||||
)
|
||||
|
||||
@@ -111,22 +107,22 @@ export interface TraitInstanceFn extends Fn {
|
||||
export type TraitApplierSuperTag = "@thilawyn/traitify-ts/TraitApplierSuper"
|
||||
|
||||
export type TraitApplier<
|
||||
AbstractMembers extends object,
|
||||
ImplWithAbstractMembers extends Class<AbstractMembers, []>,
|
||||
Abstract extends object,
|
||||
ImplWithAbstract extends Class<Abstract, []>,
|
||||
> = (
|
||||
(Super: Opaque<AbstractClass<AbstractMembers>, TraitApplierSuperTag>) => (
|
||||
Opaque<ImplWithAbstractMembers, TraitApplierSuperTag>
|
||||
(Super: Opaque<AbstractClass<Abstract>, TraitApplierSuperTag>) => (
|
||||
Opaque<ImplWithAbstract, TraitApplierSuperTag>
|
||||
)
|
||||
)
|
||||
|
||||
export function trait<
|
||||
AbstractMembers extends object = {}
|
||||
Abstract extends object = {}
|
||||
>(): (
|
||||
<ImplWithAbstractMembers extends Class<AbstractMembers, []>>(
|
||||
apply: TraitApplier<AbstractMembers, ImplWithAbstractMembers>
|
||||
<ImplWithAbstract extends Class<Abstract, []>>(
|
||||
apply: TraitApplier<Abstract, ImplWithAbstract>
|
||||
) => Trait<
|
||||
AbstractMembers,
|
||||
ImplWithAbstractMembers
|
||||
Abstract,
|
||||
RemoveAbstractFromImplClass<ImplWithAbstract, Abstract>
|
||||
>
|
||||
) {
|
||||
return apply => ({ apply }) as any
|
||||
|
||||
Reference in New Issue
Block a user