A Parcel transformer that processes TypeScript files to generate declaration files (.d.ts) with tree-shaking and module graph optimization
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
TypeScript compiler transforms for collecting module information and performing tree-shaking operations on TypeScript abstract syntax trees.
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:
Usage Example:
// Used as TypeScript compiler transform
const emitResult = program.emit(undefined, undefined, undefined, true, {
afterDeclarations: [
context => sourceFile => {
return collect(moduleGraph, context, sourceFile);
}
]
});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:
moduleGraph.propagate() to determine which types are useddeclare keywords for ambient declarationsInternal 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:
moduleGraph.getAllImports()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)
]
});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.
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;Both functions process TypeScript declarations:
type MyType = stringinterface User { name: string }class Component { }function helper() { }enum Status { Active }const config = { }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;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();
}The shake function resolves qualified names and updates references:
// Before: qualified reference
namespace.SubType
// After: direct reference (if namespace is imported)
ImportedSubTypeThe shake function removes private class members from declaration output:
class MyClass {
public publicMethod() { } // Kept
private privateMethod() { } // Removed
}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);
}The getExportedName function handles various export patterns:
export function myFunc() {} → "myFunc"export default class MyClass {} → "default"function helper() {} → nullThe isDeclaration function identifies TypeScript declaration types that can be exported:
function)class)interface)enum)type)Install with Tessl CLI
npx tessl i tessl/npm-parcel--transformer-typescript-types