@halospv3/hce.shared-config
Version:
Automate commit message quality, changelogs, and CI/CD releases. Its `main` entry point is a Semantic Release config. Functions and classes are exposed for customization. An ESLint config, a Commitlint config, and addl. resources for .NET projects are als
86 lines (80 loc) • 3.78 kB
text/typescript
/* eslint-disable jsdoc/no-defaults */
import type { TupleIndices } from '../miscTypes.ts';
import { getPrototypeOf } from './getPrototypeOf.ts';
import {
baseClassProto as baseClassPrototype,
type BaseClassProto as BaseClassPrototype,
type ClassLike,
type ConstructorConstraint,
type ProtoChainOfClass as PrototypeChainOfClass,
type ProtoChainOfClassInstance as PrototypeChainOfClassInstance,
type SuperClassLike,
type WithProto as WithPrototype,
} from './inheritance.ts';
import { isConstructor } from './isConstructor.ts';
type PrototypeChain<
Class extends ClassLike<ConstructorConstraint<Class> & WithPrototype<SuperClassLike | BaseClassPrototype>>,
ClassesOrInstances extends 'classes' | 'classInstances',
> = [ClassesOrInstances] extends ['classInstances'] ? PrototypeChainOfClassInstance<Class>
: [ClassesOrInstances] extends ['classes'] ? PrototypeChainOfClass<Class>
: never;
/**
* Iterate through the class and its base/super classes until an anonymous function is reached. This is the default superclass all classes extend.
* @template Class Any {@link ClassLike} type.
* @template ClassesOrInstances 'classes' or 'classInstances'
* @param classDefinition Any class type satisfying {@link Class}. This class (or its instance type) is included in the return value.
* @param [returnType='classes'] Determines return type. If 'classInstances', the return type is an array of the classes' `.prototype`. Else, the classes themselves are returned.
* @since 3.0.0
* @returns
* `returnType extends 'classInstances' ? ClassLike<T>[] : ClassLike<T>[].map(c => c.prototype)`
* Excludes default superclasses e.g. anonymous functions, native code.
*/
export function getPrototypesChainOf<
Class extends ClassLike<ConstructorConstraint<Class> & WithPrototype<SuperClassLike | BaseClassPrototype>>,
ClassesOrInstances extends 'classes' | 'classInstances',
>(
classDefinition: Class,
returnType: ClassesOrInstances,
): PrototypeChain<Class, ClassesOrInstances> {
// class definitions or their respective .prototype; exclude default superclasses.
let current: PrototypeChainOfClass<Class>[TupleIndices<PrototypeChainOfClass<Class>>] = classDefinition as PrototypeChainOfClass<Class>[0 extends TupleIndices<PrototypeChainOfClass<Class>> ? 0 : never];
const returnValue = [] as unknown as
PrototypeChain<Class, ClassesOrInstances>;
let index: TupleIndices<typeof returnValue> = 0 as TupleIndices<typeof returnValue>;
while (baseClassPrototype !== current) {
const parent: typeof current & WithPrototype<SuperClassLike | BaseClassPrototype> | object
= getPrototypeOf(current);
// current is a Class symbol/constructor. Object.getOwnPropertyDescriptors on current will include static properties.
if (!isConstructor(current))
break;
if (returnType === 'classInstances') {
const instanceOfCurrent = current.prototype as InstanceType<typeof current>;
returnValue[index] = instanceOfCurrent as typeof returnValue[typeof index];
}
else {
returnValue[index] = current as typeof returnValue[typeof index];
}
/**
* Assign the super class to current.
* If the argument is a class, Reflect.getPrototypeOf method returns the
* superclass.
*/
if (
isConstructor(parent)
&& 'name' in parent
&& typeof parent.name === 'string'
&& '' !== parent.name // it's possible for a Function/Constructor to be anonymous...
) {
current = parent as PrototypeChainOfClass<Class>[TupleIndices<PrototypeChainOfClass<Class>>];
}
else {
break;
}
index++;
}
return returnValue;
/*
assuming current is NugetProjectProperties...
Reflect.getPrototypeOf(current).name is 'MSBuildProjectProperties'
*/
}