// oxlint-disable no-explicit-any // ============================================================================ // Primitives // ============================================================================ /** * @description Define a constructor type for a class. * * @example * ``` * // Expect: new (name: string, age: number) => Person * type Example1 = ClassConstructor * // Expect: new () => Date * type Example2 = ClassConstructor * ``` */ export type ClassConstructor = new ( ...args: Args ) => Instance /** * @description Define an abstract constructor type for a class. * * @example * ``` * abstract class Base {} * // Expect: abstract new () => Base * type Example1 = ClassAbstractConstructor * ``` */ export type ClassAbstractConstructor< Instance = unknown, Args extends any[] = any[], > = abstract new (...args: Args) => Instance /** * @description Define a class decorator signature. * * @example * ``` * class Base {} * // Expect: (target: typeof Base) => typeof Base * type Example1 = ClassDecorator * ``` */ export type ClassDecorator any> = (target: C) => C // ============================================================================ // Validation // ============================================================================ /** * @description Check if a type is a constructor. * * @example * ``` * class Foo {} * type Factory = () => Foo * // Expect: true * type Example1 = ClassIsConstructor * // Expect: false * type Example2 = ClassIsConstructor * ``` */ export type ClassIsConstructor = T extends new (...args: any[]) => any ? true : false /** * @description Check if a type is an abstract constructor. * * @example * ``` * abstract class Base {} * class Concrete {} * // Expect: true * type Example1 = ClassIsAbstractConstructor * // Expect: false * type Example2 = ClassIsAbstractConstructor * ``` */ export type ClassIsAbstractConstructor = T extends abstract new (...args: any[]) => any ? true : false /** * @description Check if a type is a concrete (non-abstract) constructor. * * @example * ``` * abstract class Base {} * class Concrete {} * type Factory = () => Concrete * // Expect: true * type Example1 = ClassIsConcreteConstructor * // Expect: false * type Example2 = ClassIsConcreteConstructor * // Expect: false * type Example3 = ClassIsConcreteConstructor * ``` */ export type ClassIsConcreteConstructor = T extends new (...args: any[]) => any ? T extends abstract new (...args: any[]) => any ? false : true : false /** * @description Check if a constructor has parameters. * * @example * ``` * class Empty { constructor() {} } * class Person { constructor(name: string) {} } * // Expect: false * type Example1 = ClassHasConstructorParameters * // Expect: true * type Example2 = ClassHasConstructorParameters * ``` */ export type ClassHasConstructorParameters any> = ConstructorParameters extends infer P extends readonly unknown[] ? P["length"] extends 0 ? false : true : false // ============================================================================ // Comparison // ============================================================================ /** * @description Check if a value type is an instance of a class constructor. * * @example * ``` * class Person { name = 'demo' } * type Value = { name: string } * // Expect: true * type Example1 = ClassIsInstance * // Expect: false * type Example2 = ClassIsInstance * ``` */ export type ClassIsInstance any> = Value extends InstanceType ? true : false /** * @description Check if class A extends class B (structurally by instance type). * * @example * ``` * class Base { id = 1 } * class Derived extends Base {} * // Expect: true * type Example1 = ClassIsExtend * // Expect: false * type Example2 = ClassIsExtend * ``` */ export type ClassIsExtend< A extends abstract new (...args: any[]) => any, B extends abstract new (...args: any[]) => any, > = InstanceType extends InstanceType ? true : false /** * @description Check if class C implements interface I (structurally by instance type). * * @example * ``` * interface Shape { area(): number } * class Square implements Shape { area() { return 1 } } * // Expect: true * type Example1 = ClassIsImplement * // Expect: false * type Example2 = ClassIsImplement * ``` */ export type ClassIsImplement any, I> = InstanceType extends I ? true : false // ============================================================================ // Query // ============================================================================ /** * @description Get constructor parameters of a class. * * @example * ``` * class Person { constructor(name: string, age: number) {} } * class Empty { constructor() {} } * // Expect: [name: string, age: number] * type Example1 = ClassConstructorParameters * // Expect: [] * type Example2 = ClassConstructorParameters * ``` */ export type ClassConstructorParameters any> = ConstructorParameters /** * @description Get the constructor parameter at index N. * * @example * ``` * class Person { constructor(name: string, age: number) {} } * // Expect: string * type Example1 = ClassConstructorParameterAt * // Expect: number * type Example2 = ClassConstructorParameterAt * // Expect: never * type Example3 = ClassConstructorParameterAt * ``` */ export type ClassConstructorParameterAt< C extends abstract new (...args: any[]) => any, Index extends number, > = ConstructorParameters extends infer P extends readonly unknown[] ? Index extends keyof P ? P[Index] : never : never /** * @description Get constructor arity (parameter count). * * @example * ``` * class Person { constructor(name: string, age: number) {} } * class Empty { constructor() {} } * // Expect: 2 * type Example1 = ClassConstructorArity * // Expect: 0 * type Example2 = ClassConstructorArity * ``` */ export type ClassConstructorArity any> = ConstructorParameters["length"] /** * @description Get instance type from a class constructor. * * @example * ``` * class Person { name = 'demo' } * // Expect: Person * type Example1 = ClassInstanceType * ``` */ export type ClassInstanceType any> = InstanceType /** * @description Get instance type from an abstract constructor. * * @example * ``` * abstract class Base { id = 1 } * // Expect: Base * type Example1 = ClassAbstractInstanceType * ``` */ export type ClassAbstractInstanceType any> = InstanceType type InternalInstanceRecord any> = InstanceType extends infer I ? { [K in keyof I]: I[K] } : never /** * @description Get all public keys on a class instance. * * @example * ``` * class Person { name = 'demo'; age = 1; greet() {} } * // Expect: 'name' | 'age' | 'greet' * type Example1 = ClassPublicKeys * ``` */ export type ClassPublicKeys any> = keyof InternalInstanceRecord type InternalFunctionKeys> = { [K in keyof T]-?: T[K] extends (...args: any[]) => any ? K : never }[keyof T] /** * @description Get method keys from a class instance. * * @example * ``` * class Person { name = 'demo'; greet() {} } * // Expect: 'greet' * type Example1 = ClassMethodKeys * ``` */ export type ClassMethodKeys any> = InternalFunctionKeys< InternalInstanceRecord > type InternalNonFunctionKeys> = { [K in keyof T]-?: T[K] extends (...args: any[]) => any ? never : K }[keyof T] /** * @description Get field keys (non-function) from a class instance. * * @example * ``` * class Person { name = 'demo'; greet() {} } * // Expect: 'name' * type Example1 = ClassFieldKeys * ``` */ export type ClassFieldKeys any> = InternalNonFunctionKeys> type InternalIfEquals = (() => T extends X ? 1 : 2) extends () => T extends Y ? 1 : 2 ? TRUE : FALSE type InternalReadonlyKeys> = { [K in keyof T]-?: InternalIfEquals<{ [Q in K]: T[K] }, { -readonly [Q in K]: T[K] }, never, K> }[keyof T] /** * @description Get readonly keys from a class instance. * * @example * ``` * class Person { readonly id = 1; name = 'demo' } * // Expect: 'id' * type Example1 = ClassReadonlyKeys * ``` */ export type ClassReadonlyKeys any> = InternalReadonlyKeys> type InternalWritableKeys> = { [K in keyof T]-?: InternalIfEquals<{ [Q in K]: T[K] }, { -readonly [Q in K]: T[K] }, K, never> }[keyof T] /** * @description Get writable keys from a class instance. * * @example * ``` * class Person { readonly id = 1; name = 'demo' } * // Expect: 'name' * type Example1 = ClassWritableKeys * ``` */ export type ClassWritableKeys any> = InternalWritableKeys> /** * @description Get static keys from a class constructor. * * @example * ``` * class Person { static role = 'user'; name = 'demo' } * // Expect: 'prototype' | 'role' * type Example1 = ClassStaticKeys * ``` */ export type ClassStaticKeys any> = keyof C // ============================================================================ // Extraction // ============================================================================ /** * @description Pick static members from a class constructor. * * @example * ``` * class Person { static role = 'user'; static version = 1; name = 'demo' } * // Expect: { role: string } * type Example1 = ClassStaticPick * ``` */ export type ClassStaticPick< C extends abstract new (...args: any[]) => any, K extends keyof C, > = Pick // ============================================================================ // Manipulation // ============================================================================ /** * @description Apply a mixin to a class constructor. * * @example * ``` * class Base { base = true } * type Mixin = (base: typeof Base) => abstract new (...args: any[]) => Base & { extra: string } * // Expect: abstract new (...args: any[]) => Base & { extra: string } * type Example1 = ClassWithMixin * ``` */ export type ClassWithMixin< C extends abstract new (...args: any[]) => any, M extends (base: C) => abstract new (...args: any[]) => any, > = M extends (base: C) => infer Result ? Result : never /** * @description Apply a decorator to a class constructor. * * @example * ``` * class Base {} * type Decorator = (target: typeof Base) => typeof Base * // Expect: typeof Base * type Example1 = ClassDecorate * ``` */ export type ClassDecorate< C extends abstract new (...args: any[]) => any, D extends (target: C) => C, > = D extends (target: C) => infer Result ? Result : never // ============================================================================ // Conversion // ============================================================================ /** * @description Convert a class constructor to a regular function signature. * * @example * ``` * class Person { constructor(name: string, age: number) {} } * // Expect: (name: string, age: number) => Person * type Example1 = ClassConstructorToFunction * ``` */ export type ClassConstructorToFunction any> = ( ...args: ConstructorParameters ) => InstanceType