Class ReflectionTransformer

Read the TypeScript AST and generate pack struct (instructions + pre-defined stack).

This transformer extracts type and add the encoded (so its small and low overhead) at classes and functions as property.

Deepkit/type can then extract and decode them on-demand.

Hierarchy

Implements

  • CustomTransformer

Constructors

Properties

addImports: {
    from: Expression;
    identifier: Identifier;
}[] = []
compileDeclarations: Map<InterfaceDeclaration | TypeAliasDeclaration | EnumDeclaration, {
    compiled?: Statement[];
    name: EntityName;
    sourceFile: SourceFile;
}> = ...

Types added to this map will get a type program directly under it. This is for types used in the very same file.

compiledDeclarations: Set<Node> = ...

When a node was embedded or compiled (from the maps above), we store it here to know to not add it again.

context: TransformationContext
currentReflectionConfig: ReflectionConfig = ...
defaultExcluded: string[] = ...
embedAssignType: boolean = false
embedDeclarations: Map<Node, {
    name: EntityName;
    sourceFile: SourceFile;
}> = ...

Types added to this map will get a type program at the top root level of the program. This is for imported types, which need to be inlined into the current file, as we do not emit type imports (TS will omit them).

f: NodeFactory
globalSourceFiles?: SourceFile[]
host: CompilerHost
knownClasses: {
    [name: string]: ReflectionOp;
} = ...

Type declaration

  • [name: string]: ReflectionOp
nodeConverter: NodeConverter
reflectionMode?: "default" | "always" | "never"
reflectionOptions?: ReflectionOptions
resolvedPackageJson: {
    [path: string]: {
        data: Record<string, any>;
        exists: boolean;
    };
} = {}

Type declaration

  • [path: string]: {
        data: Record<string, any>;
        exists: boolean;
    }
    • data: Record<string, any>
    • exists: boolean
resolvedTsConfig: {
    [path: string]: {
        data: Record<string, any>;
        exists: boolean;
    };
} = {}

Type declaration

  • [path: string]: {
        data: Record<string, any>;
        exists: boolean;
    }
    • data: Record<string, any>
    • exists: boolean
resolver: Resolver
sourceFile: SourceFile
tempResultIdentifier?: Identifier

When an deep call expression was found a script-wide variable is necessary as temporary storage.

typeChecker?: TypeChecker

Methods

  • Parameters

    • node: Node
    • name: EntityName
    • sourceFile: SourceFile

    Returns Statement[]

  • const fn = () => { } => const fn = Object.assign(() => {}, {__type: 34})

    Parameters

    • expression: ArrowFunction

    Returns ArrowFunction | CallExpression

  • A class is decorated with type information by adding a static variable.

    class Model { static __types = pack(ReflectionOp.string); //<-- encoded type information title: string; }

    Parameters

    • node: ClassDeclaration | ClassExpression

    Returns Node

  • function name() {}

    => function name() {}; name.__type = 34;

    Parameters

    • declaration: FunctionDeclaration

    Returns undefined | FunctionDeclaration | ExportAssignment | Statement[]

  • const fn = function() {}

    => const fn = __assignType(function() {}, [34])

    Parameters

    • expression: FunctionExpression

    Returns FunctionExpression | CallExpression

  • Parameters

    • node: Node | Declaration | ClassDeclaration | ClassExpression
    • program: CompilerProgram

    Returns void

  • Parameters

    • type: TypeReferenceNode | ExpressionWithTypeArguments
    • program: CompilerProgram

    Returns void

  • Parameters

    • sourceFile: ModuleDeclaration | SourceFile
    • declarationName: __String

    Returns undefined | Declaration

  • Parameters

    • declarationName: __String
    • statement: ExportDeclaration
    • sourceFile: SourceFile

    Returns undefined | Declaration

  • Type Parameters

    • T extends FunctionExpression | FunctionDeclaration | ConstructorDeclaration | MethodDeclaration

    Parameters

    • node: T

    Returns T

  • With this function we want to check if type is used in the signature itself from the parent of declaration. If so, we do not try to infer the type from runtime values.

    Examples where we do not infer from runtime, type being T and declaration being <T> (return false):

    class User<T> {
    config: T;
    }

    class User<T> {
    constructor(public config: T) {}
    }

    function do<T>(item: T): void {}
    function do<T>(item: T): T {}

    Examples where we infer from runtime (return true):

    function do<T>(item: T) {
    return typeOf<T>; //<-- because of that
    }

    function do<T>(item: T) {
    class A {
    config: T; //<-- because of that
    }
    return A;
    }

    function do<T>(item: T) {
    class A {
    doIt() {
    class B {
    config: T; //<-- because of that
    }
    return B;
    }
    }
    return A;
    }

    function do<T>(item: T) {
    class A {
    doIt(): T { //<-- because of that
    }
    }
    return A;
    }

    Parameters

    • declaration: TypeParameterDeclaration
    • type: TypeReferenceNode | ExpressionWithTypeArguments

    Returns boolean

  • Parameters

    • Optional mode: boolean | "" | string[] | "default" | "always" | "never"
    • Optional configPathDir: string

    Returns "default" | "always" | "never"

  • This is a custom resolver based on populated locals from the binder. It uses a custom resolution algorithm since we have no access to the binder/TypeChecker directly and instantiating a TypeChecker per file/transformer is incredible slow.

    Parameters

    • typeName: EntityName

    Returns void | {
        declaration: Node;
        importDeclaration?: ImportDeclaration;
        typeOnly?: boolean;
    }

  • Parameters

    • declarationName: __String
    • importOrExport: ImportDeclaration | ExportDeclaration
    • sourceFile: SourceFile

    Returns undefined | Declaration

  • Parameters

    • declaration: TypeParameterDeclaration
    • type: TypeReferenceNode | ExpressionWithTypeArguments
    • program: CompilerProgram

    Returns void

  • Parameters

    • sourceFile: SourceFile

    Returns SourceFile

  • Note: We have to duplicate the expressions as it can be that incoming expression are from another file and contain wrong pos/end properties, so the code generation is then broken when we simply reuse them. Wrong code like User.__type = [.toEqual({ is then generated. This function is probably not complete, but we add new copies when required.

    Parameters

    • value: undefined | PackExpression | PackExpression[]

    Returns Expression

  • Object.assign(fn, {__type: []}) is much slower than a custom implementation like

    assignType(fn, [])

    where we embed assignType() at the beginning of the type.

    Parameters

    • fn: Expression
    • type: Expression

    Returns CallExpression

Generated using TypeDoc