# core/predicates/construct.predicate.ts

> 53 lines of code and 7 definitions.

Tree: GovLab Quality
Language: typescript
Layer: infrastructure
Canonical: https://banes-lab.com/anatomy/quality#file-quality-core-predicates-construct-predicate-ts
Source text: https://banes-lab.com/source/quality/core/predicates/construct.predicate.ts.txt

Listed in [core/predicates](https://banes-lab.com/api/source/quality/core/predicates.md), after [core/predicates/constants.predicate.ts](https://banes-lab.com/source/quality/core/predicates/constants.predicate.ts.md) and before [core/predicates/context.fragment.predicate.ts](https://banes-lab.com/source/quality/core/predicates/context.fragment.predicate.ts.md).

## Definitions

- `isConstructInit` (lexical_declaration, line 31, exported)
- `isFn` (lexical_declaration, line 4)
- `isInstanceOrFactory` (lexical_declaration, line 20)
- `isDefaultConstruct` (lexical_declaration, line 49, exported)
- `isFactoryCallName` (lexical_declaration, line 8)
- `next` (lexical_declaration, line 11)
- `{ callee }` (lexical_declaration, line 21)

## Contained in

- [core/predicates](https://banes-lab.com/anatomy/quality/folder-quality-core-predicates.md)

## Used by

- [core/quality/eslint/require-test-coverage.eslint.rule.ts](https://banes-lab.com/source/quality/core/quality/eslint/require-test-coverage.eslint.rule.ts.md)
- [core/selectors/construct.selector.ts](https://banes-lab.com/source/quality/core/selectors/construct.selector.ts.md)

## Linked from

- [core/predicates](https://banes-lab.com/anatomy/quality/folder-quality-core-predicates.md)
- [core/quality/eslint](https://banes-lab.com/anatomy/quality/folder-quality-core-quality-eslint.md)
- [core/selectors](https://banes-lab.com/anatomy/quality/folder-quality-core-selectors.md)

## Source

```typescript
import { DATA_CONSTRUCTORS, FACTORY_PREFIXES } from "#configuration/constants/construct.constants";
import type { ConstructNode } from "#types/construct.types";

const isFn = function isFn(node: ConstructNode | null | undefined): boolean {
    return node?.type === "ArrowFunctionExpression" || node?.type === "FunctionExpression";
};

const isFactoryCallName = function isFactoryCallName(name: string): boolean {
    for (const prefix of FACTORY_PREFIXES) {
        if (name.startsWith(prefix) && name.length > prefix.length) {
            const next = name.charAt(prefix.length);
            if (next >= "A" && next <= "Z") {
                return true;
            }
        }
    }
    return false;
};

const isInstanceOrFactory = function isInstanceOrFactory(init: ConstructNode): boolean {
    const { callee } = init;
    if (callee?.type !== "Identifier" || typeof callee.name !== "string") {
        return false;
    }
    if (init.type === "NewExpression") {
        return !DATA_CONSTRUCTORS.has(callee.name);
    }
    return isFactoryCallName(callee.name);
};

export const isConstructInit = function isConstructInit(init: ConstructNode | null | undefined): boolean {
    if (!init) {
        return false;
    }
    if (isFn(init)) {
        return true;
    }
    if (init.type === "ObjectExpression") {
        return (init.properties ?? []).some(
            (prop) => prop.type === "Property" && (prop.method === true || isFn(prop.value)),
        );
    }
    if (init.type === "CallExpression" || init.type === "NewExpression") {
        return isInstanceOrFactory(init);
    }
    return false;
};

export const isDefaultConstruct = function isDefaultConstruct(declaration?: ConstructNode | null): boolean {
    if (!declaration) {
        return false;
    }
    return (
        declaration.type === "FunctionDeclaration" ||
        declaration.type === "ClassDeclaration" ||
        isConstructInit(declaration)
    );
};
```
