CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-parcel--transformer-typescript-types

A Parcel transformer that processes TypeScript files to generate declaration files (.d.ts) with tree-shaking and module graph optimization

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

ast-processing.mddocs/

AST Processing

TypeScript compiler transforms for collecting module information and performing tree-shaking operations on TypeScript abstract syntax trees.

Capabilities

collect Function

TypeScript compiler transform that builds the module dependency graph by analyzing imports, exports, and declarations in TypeScript source files.

/**
 * Collects module information from TypeScript AST nodes
 * First phase transform that builds the dependency graph
 * @param moduleGraph - Module graph to populate
 * @param context - TypeScript transform context
 * @param sourceFile - TypeScript source file AST node
 * @returns Modified AST with synthetic imports for import types
 */
function collect(
  moduleGraph: TSModuleGraph,
  context: any,
  sourceFile: any
): any;

Collection Process:

The collect function performs the following operations:

  1. Module Declaration Handling: Processes nested module declarations and maintains module hierarchy
  2. Import Analysis: Extracts all import statements including named, default, and namespace imports
  3. Export Analysis: Collects export declarations, re-exports, and export assignments
  4. Declaration Processing: Records all type declarations, interfaces, classes, functions, and variables
  5. Import Type Transformation: Converts TypeScript import types to regular type references with synthetic imports

Usage Example:

// Used as TypeScript compiler transform
const emitResult = program.emit(undefined, undefined, undefined, true, {
  afterDeclarations: [
    context => sourceFile => {
      return collect(moduleGraph, context, sourceFile);
    }
  ]
});

shake Function

TypeScript compiler transform that removes unused types and renames symbols while flattening module declarations.

/**
 * Performs tree-shaking and symbol renaming on TypeScript AST
 * Second phase transform that optimizes the declaration output
 * @param moduleGraph - Module graph with usage information
 * @param context - TypeScript transform context
 * @param sourceFile - TypeScript source file AST node
 * @returns Optimized AST with unused types removed and symbols renamed
 */
function shake(
  moduleGraph: TSModuleGraph,
  context: any,
  sourceFile: any
): any;

Tree-shaking Process:

The shake function performs these optimizations:

  1. Usage Propagation: Calls moduleGraph.propagate() to determine which types are used
  2. Import Hoisting: Moves all import statements to the top level of the output
  3. Module Flattening: Flattens nested module declarations into the top-level scope
  4. Declaration Filtering: Removes unused type declarations, interfaces, and functions
  5. Symbol Renaming: Updates all references to use renamed symbols
  6. Export Optimization: Removes internal exports and preserves only public API exports
  7. Modifier Management: Adds declare keywords for ambient declarations

generateImports Function

Internal helper function used by the shake transform to create optimized import statements at the top of the output.

/**
 * Generates import statements for all external dependencies
 * Called internally by shake function to hoist imports to the top
 * @param factory - TypeScript node factory for creating AST nodes
 * @param moduleGraph - Module graph containing import information
 * @returns Array of ImportDeclaration AST nodes for external modules
 */
function generateImports(factory: any, moduleGraph: TSModuleGraph): any[];

Import Generation Process:

  1. External Import Collection: Gets all imports to external modules via moduleGraph.getAllImports()
  2. Import Type Categorization: Separates default, namespace, and named imports
  3. Import Statement Creation: Uses compatibility wrappers to create version-appropriate import nodes
  4. Deduplication: Combines multiple imports from the same module into single statements

Usage Example:

// Used as TypeScript compiler transform
const emitResult = program.emit(undefined, undefined, undefined, true, {
  afterDeclarations: [
    // First collect phase
    context => sourceFile => collect(moduleGraph, context, sourceFile),
    // Then shake phase
    context => sourceFile => shake(moduleGraph, context, sourceFile)
  ]
});

AST Node Processing

Import Statement Processing

The collect function handles various import patterns:

// Named imports
import { Button, Dialog } from './components';

// Default imports  
import React from 'react';

// Namespace imports
import * as utils from './utils';

// Mixed imports
import React, { Component } from 'react';

Each import type is processed and stored in the module's import map with appropriate specifier and imported name tracking.

Export Statement Processing

The collect function handles export patterns:

// Named exports
export { Button } from './button';
export function createDialog() { }

// Default exports
export default class App { }

// Re-exports
export * from './components';

// Export assignments
export = SomeValue;

Declaration Processing

Both functions process TypeScript declarations:

  • Type Aliases: type MyType = string
  • Interfaces: interface User { name: string }
  • Classes: class Component { }
  • Functions: function helper() { }
  • Enums: enum Status { Active }
  • Variables: const config = { }

Import Type Transformation

The collect function converts TypeScript import types to regular imports:

// Before: import type syntax
type ReactElement = import('react').ReactElement;

// After: regular import with synthetic identifier
import { ReactElement as $$parcel$import$0 } from 'react';
type ReactElement = $$parcel$import$0;

AST Visitor Patterns

Module Hierarchy Tracking

Both functions maintain a module stack to handle nested module declarations:

const moduleStack = [];
let currentModule = null;

// Push/pop modules as we enter/exit module declarations
if (ts.isModuleDeclaration(node)) {
  moduleStack.push(currentModule);
  currentModule = new TSModule();
}

Symbol Reference Resolution

The shake function resolves qualified names and updates references:

// Before: qualified reference
namespace.SubType

// After: direct reference (if namespace is imported)
ImportedSubType

Private Member Filtering

The shake function removes private class members from declaration output:

class MyClass {
  public publicMethod() { }    // Kept
  private privateMethod() { }  // Removed
}

Utility Functions

Helper functions for AST node analysis and processing.

/**
 * Extracts the exported name from a TypeScript declaration node
 * @param node - TypeScript AST node (declaration with potential modifiers)
 * @returns Export name ('default' for default exports, symbol name for named exports, null if not exported)
 */
function getExportedName(node: any): string | null;

/**
 * Checks if an AST node is a TypeScript declaration that can be exported
 * @param node - TypeScript AST node to check
 * @returns True if node is a function, class, interface, enum, or type alias declaration
 */
function isDeclaration(node: any): boolean;

/**
 * Internal helper that processes import type nodes to extract import information
 * Used by collect transform to convert import() types to regular imports
 * @param qualifier - EntityName qualifier from import type (optional)
 * @param local - Local identifier name for the synthetic import
 * @param factory - TypeScript node factory for creating AST nodes
 * @returns Tuple of [importSpecifier, entityReference] for the transformed import
 */
function getImportName(
  qualifier: any,
  local: string,
  factory: any
): [string, any];

Usage Examples:

import { getExportedName, isDeclaration } from '@parcel/transformer-typescript-types';

// Check if node is exportable declaration
if (isDeclaration(node)) {
  const exportName = getExportedName(node);
  if (exportName) {
    // Node is exported with name
    currentModule.addExport(exportName, exportName);
  }
}

// Process import types during collection
if (ts.isImportTypeNode(node)) {
  let local = `$$parcel$import$${moduleGraph.syntheticImportCount++}`;
  let [specifier, entity] = getImportName(node.qualifier, local, factory);
  currentModule.addImport(local, node.argument.literal.text, specifier);
  
  // Transform: import('react').JSX.Element → JSX.Element
  // With synthetic import: import { JSX } from 'react'
  return factory.createTypeReferenceNode(entity, node.typeArguments);
}

Export Name Detection

The getExportedName function handles various export patterns:

  • Named exports: export function myFunc() {}"myFunc"
  • Default exports: export default class MyClass {}"default"
  • Non-exported: function helper() {}null

Declaration Type Detection

The isDeclaration function identifies TypeScript declaration types that can be exported:

  • Function declarations (function)
  • Class declarations (class)
  • Interface declarations (interface)
  • Enum declarations (enum)
  • Type alias declarations (type)

Install with Tessl CLI

npx tessl i tessl/npm-parcel--transformer-typescript-types

docs

ast-processing.md

index.md

module-graph.md

transformer.md

ts-compatibility.md

tile.json