Declaration Files for Components
apps/docs/src/content/docs/components/typescript/declarations Click to copy apps/docs/src/content/docs/components/typescript/declarations TypeScript declaration files (.d.ts) are the interface contract between hx-library and its consumers. They enable type checking, IDE autocomplete, and “Go to Definition” navigation without exposing implementation details. This guide covers automatic generation, module augmentation patterns, declaration maps, and best practices for maintaining type accuracy across the component library.
What Are Declaration Files?
Section titled “What Are Declaration Files?”Declaration files contain only type information—no runtime code. They describe the shape of JavaScript modules to TypeScript’s type checker and language services. When you import an hx-library component, TypeScript uses its .d.ts file to validate property assignments, method calls, and event handlers at compile time.
Declaration Files vs. Source Files
Section titled “Declaration Files vs. Source Files”// src/components/hx-button/hx-button.ts (source — simplified)import { html } from 'lit';import { customElement, property } from 'lit/decorators.js';import { HelixElement } from '../../base/helix-element.js';import { mixinDelegatesAria } from '../../mixins/index.js';
@customElement('hx-button')export class HelixButton extends mixinDelegatesAria(HelixElement) { @property({ type: String, reflect: true }) variant: 'primary' | 'secondary' | 'tertiary' | 'danger' | 'ghost' | 'outline' = 'primary';
@property({ type: Boolean, reflect: true }) disabled = false;
render() { return html`<button part="button"><slot></slot></button>`; } // Private fields, internal state controllers, and reactive // event handlers are also defined on this class — those are // emitted into the .d.ts (see below), they just have no // implementation body in the declaration.}// dist/components/hx-button/index.d.ts (generated declaration)import { HelixElement } from '../../base/helix-element.js';
export declare class HelixButton extends HelixElement { variant: 'primary' | 'secondary' | 'tertiary' | 'danger' | 'ghost' | 'outline'; disabled: boolean; // Private fields are emitted with the # prefix so TS knows the // class shape; their type is preserved without an implementation // body. Internal controllers and event handlers similarly retain // their type but no body. render(): unknown;}
declare global { interface HTMLElementTagNameMap { 'hx-button': HelixButton; }}Key differences:
- Implementation bodies are stripped, but the class shape (including private fields with
#-prefixed names, controllers, and event handlers) is preserved so TypeScript can still type-check consumer code against the full surface. - Explicit
declarekeyword: Signals to TypeScript this is ambient type information (no runtime code) - Preserved type annotations: Public API types remain intact (
variant: 'primary' | 'secondary' | 'tertiary' | 'danger' | 'ghost' | 'outline') - Inferred complex types: Return types narrow to whatever Lit’s type definitions produce (often
unknownorTemplateResultdepending on tsconfig).
Automatic Declaration Generation
Section titled “Automatic Declaration Generation”hx-library uses TypeScript’s compiler (tsc) via the vite-plugin-dts Vite plugin to generate .d.ts files automatically during the build process. This ensures declarations stay synchronized with source code without manual maintenance.
TypeScript Compiler Configuration
Section titled “TypeScript Compiler Configuration”The tsconfig.json enables declaration generation. (TypeScript accepts JSONC — JSON with
comments — in tsconfig files; the comments in the sample below are part of the supported syntax,
but if you’re feeding this snippet to a strict JSON parser strip the comments first.)
{ "extends": "../../tsconfig.base.json", "compilerOptions": { "composite": true, "outDir": "./dist", "rootDir": "./src", "declaration": true, // Generate .d.ts files "declarationMap": true, // Generate .d.ts.map source maps "sourceMap": true, // Generate .js.map source maps "experimentalDecorators": true, "useDefineForClassFields": false, "lib": ["ES2022", "DOM", "DOM.Iterable"] }, "include": ["src/**/*.ts"], "exclude": [ "node_modules", "dist", "src/**/*.stories.ts", // Storybook stories are not library API "src/**/*.test.ts", // Tests are not library API "src/test-utils.ts" ]}Critical settings:
| Setting | Purpose |
|---|---|
declaration: true | Generate .d.ts files alongside .js output |
declarationMap: true | Generate .d.ts.map files for IDE source navigation |
sourceMap: true | Generate .js.map files for browser debugging |
composite: true | Enable TypeScript project references (monorepo optimization) |
Vite Plugin Integration
Section titled “Vite Plugin Integration”The vite-plugin-dts plugin orchestrates declaration generation during Vite’s build:
import { defineConfig } from 'vite';import { resolve } from 'path';import dts from 'vite-plugin-dts';
export default defineConfig({ plugins: [ dts({ include: ['src/**/*.ts'], exclude: ['**/*.test.ts', '**/*.stories.ts'], }), ], build: { lib: { entry: { index: resolve(__dirname, 'src/index.ts'), 'components/hx-button/index': resolve(__dirname, 'src/components/hx-button/index.ts'), 'components/hx-card/index': resolve(__dirname, 'src/components/hx-card/index.ts'), // ... other entry points }, formats: ['es'], }, outDir: 'dist', sourcemap: true, minify: 'esbuild', },});How it works:
- Vite builds JavaScript: Source TypeScript compiles to ESM in
dist/ - Plugin runs
tsc --emitDeclarationOnly: TypeScript generates.d.tsfiles without re-compiling JavaScript - Output mirrors source structure:
src/components/hx-button/hx-button.ts→dist/components/hx-button/hx-button.d.ts
Build Output Structure
Section titled “Build Output Structure”After running npm run build:
packages/hx-library/├── src/│ ├── index.ts│ └── components/│ ├── hx-button/│ │ ├── index.ts│ │ ├── hx-button.ts│ │ └── hx-button.styles.ts│ └── hx-card/│ ├── index.ts│ ├── hx-card.ts│ └── hx-card.styles.ts└── dist/ # Generated output ├── index.js # ESM JavaScript ├── index.d.ts # Type declarations ├── index.d.ts.map # Declaration source map └── components/ ├── hx-button/ │ ├── index.js │ ├── index.d.ts # Component types │ ├── index.d.ts.map │ ├── hx-button.d.ts # Class implementation types │ └── hx-button.styles.d.ts └── hx-card/ ├── index.js ├── index.d.ts └── ...Declaration File Anatomy
Section titled “Declaration File Anatomy”A component’s declaration file contains four key elements: class signature, property types, method signatures, and global augmentation.
Component Class Declaration
Section titled “Component Class Declaration”The exported class signature describes the public API:
import { LitElement } from 'lit';
export declare class HelixButton extends LitElement { static styles: import('lit').CSSResult[];
// Properties (typed, no default values) variant: 'primary' | 'secondary' | 'ghost'; size: 'sm' | 'md' | 'lg'; disabled: boolean; type: 'button' | 'submit' | 'reset';
// Form integration static formAssociated: boolean; private _internals; constructor(); get form(): HTMLFormElement | null;
// Methods (no bodies, only signatures) render(): import('lit-html').TemplateResult<1>;
// Private members (excluded from autocomplete but preserved for internal use) private _handleClick;}Why declare?
The declare keyword tells TypeScript this is ambient type information. The class exists at runtime (defined in the .js file), but this file only describes its shape for type checking.
Property Type Preservation
Section titled “Property Type Preservation”TypeScript preserves property types exactly as written in source code:
// Source: Union type for variant@property({ type: String, reflect: true })variant: 'primary' | 'secondary' | 'tertiary' | 'danger' | 'ghost' | 'outline' = 'primary';
// Declaration: Union type preserved (default value omitted)variant: 'primary' | 'secondary' | 'tertiary' | 'danger' | 'ghost' | 'outline';Consumer benefit:
import { HelixButton } from '@helixui/library/components/hx-button';
const button = document.createElement('hx-button');button.variant = 'primary'; // ✅ Validbutton.variant = 'danger'; // ✅ Valid — danger is a real hx-button variantbutton.variant = 'patient'; // ❌ Type error: not in unionMethod Signatures
Section titled “Method Signatures”Method signatures include parameter types and return types, but no implementation:
// Sourcerender() { return html`<button part="button"><slot></slot></button>`;}
// Declarationrender(): import('lit-html').TemplateResult<1>;TypeScript infers the return type (TemplateResult<1>) from Lit’s html tagged template. The <1> generic parameter indicates this is a standard template (not an SVG template, which would be TemplateResult<2>).
JSDoc Comment Preservation
Section titled “JSDoc Comment Preservation”JSDoc comments from source files are preserved in declarations, powering IDE tooltips and documentation generators:
/** * A button component for user interaction. * * @summary Primary interactive element for triggering actions. * * @tag hx-button * * @slot - Default slot for button label text or content. * * @fires {CustomEvent<{originalEvent: MouseEvent}>} hx-click - Dispatched when the button is clicked. * * @csspart button - The native button element. * * @cssprop [--hx-button-bg=var(--hx-color-action-primary-bg)] - Button background color (resolves through the semantic action layer to primary-700 on the default Apex brand). */export declare class HelixButton extends LitElement { /** * Visual style variant of the button. * @attr variant */ variant: 'primary' | 'secondary' | 'ghost';}When a developer hovers over HelixButton in VS Code, they see this documentation inline.
Module Augmentation (HTMLElementTagNameMap)
Section titled “Module Augmentation (HTMLElementTagNameMap)”TypeScript’s DOM library includes the HTMLElementTagNameMap interface, which maps tag names to element classes. By default, custom elements resolve to HTMLElement. Module augmentation overrides this to provide component-specific types.
The Problem Without Augmentation
Section titled “The Problem Without Augmentation”Without HTMLElementTagNameMap augmentation:
// TypeScript infers: HTMLElement | nullconst button = document.querySelector('hx-button');
// Error: Property 'variant' does not exist on type 'HTMLElement'button.variant = 'primary';TypeScript doesn’t know <hx-button> is a HelixButton instance. You’d need manual type assertions everywhere:
const button = document.querySelector('hx-button') as HelixButton;button.variant = 'primary'; // Now it works, but verboseThe Solution: Global Augmentation
Section titled “The Solution: Global Augmentation”Every component declaration file includes a global augmentation:
declare global { interface HTMLElementTagNameMap { 'hx-button': HelixButton; }}What this does:
- Extends the global
HTMLElementTagNameMapinterface with the mapping'hx-button' → HelixButton - Enables type-safe DOM queries: TypeScript now infers
querySelector('hx-button')returnsHelixButton | null - Autocomplete in IDEs: VS Code suggests
variant,size,disabledwhen typingbutton.
Consumer Benefit
Section titled “Consumer Benefit”After importing the component (which loads its .d.ts file):
import '@helixui/library/components/hx-button';
// TypeScript knows this is HelixButton | nullconst button = document.querySelector('hx-button');
if (button) { button.variant = 'secondary'; // ✅ Type-checked button.disabled = true; // ✅ Type-checked button.size = 'xl'; // ❌ Error: 'xl' not in union type}
// Works with createElement tooconst newButton = document.createElement('hx-button');newButton.variant = 'ghost'; // ✅ HelixButton type inferredAugmentation for Multiple Components
Section titled “Augmentation for Multiple Components”When importing the full library, all components augment HTMLElementTagNameMap:
// dist/index.d.ts (barrel export)export { HelixButton } from './components/hx-button/hx-button.js';export { HelixCard } from './components/hx-card/hx-card.js';export { HelixTextInput } from './components/hx-text-input/hx-text-input.js';// ... all components
declare global { interface HTMLElementTagNameMap { 'hx-button': HelixButton; 'hx-card': HelixCard; 'hx-text-input': HelixTextInput; 'hx-checkbox': HelixCheckbox; 'hx-select': HelixSelect; // ... all tags }}Pattern: Scoped Tag Names
Section titled “Pattern: Scoped Tag Names”For type safety, use template literal types to enforce tag name prefixes:
type HelixTagName = `hx-${string}`;
function getHelixComponent(tag: HelixTagName): HTMLElement | null { return document.querySelector(tag);}
getHelixComponent('hx-button'); // ✅ ValidgetHelixComponent('button'); // ❌ Error: doesn't match patternDeclaration Maps (Source Navigation)
Section titled “Declaration Maps (Source Navigation)”Declaration maps (.d.ts.map files) enable “Go to Definition” navigation from declaration files back to original source files. Without them, IDEs jump to the .d.ts file (type information only). With them, IDEs jump to the .ts source (full implementation).
Enabling Declaration Maps
Section titled “Enabling Declaration Maps”Set declarationMap: true in tsconfig.json:
{ "compilerOptions": { "declaration": true, "declarationMap": true }}Output:
dist/components/hx-button/├── hx-button.d.ts├── hx-button.d.ts.map # Source map linking to src/└── hx-button.jsDeclaration Map Format
Section titled “Declaration Map Format”A .d.ts.map file is a JSON source map:
{ "version": 3, "file": "hx-button.d.ts", "sourceRoot": "", "sources": ["../../../src/components/hx-button/hx-button.ts"], "names": [], "mappings": "AAAA;AACA;AACA..."}The sources array points to the original .ts file. The mappings string encodes line/column positions using Base64 VLQ encoding (same as JavaScript source maps).
IDE Integration
Section titled “IDE Integration”When a consumer clicks “Go to Definition” on HelixButton:
- Without declaration map: IDE opens
dist/components/hx-button/hx-button.d.ts(declaration file) - With declaration map: IDE opens
src/components/hx-button/hx-button.ts(source file)
Developer experience benefit:
- See full implementation (not just type signature)
- Jump to method bodies, property decorators, and render logic
- Debug library code during development
Debugging in Monorepos
Section titled “Debugging in Monorepos”In monorepo setups (like hx-library), declaration maps enable cross-package navigation:
import { HelixButton } from '@helixui/library/components/hx-button';
const button = new HelixButton();// Cmd+Click on HelixButton → jumps to packages/hx-library/src/components/hx-button/hx-button.tsThis works because:
@helixui/libraryis a workspace dependency (not downloaded from npm)- Source files are accessible in the monorepo
- Declaration map
sourcespaths resolve correctly viatsconfig.jsonpath mapping
Ambient Declarations
Section titled “Ambient Declarations”Ambient declarations describe types for modules that exist at runtime but lack TypeScript definitions. While hx-library generates its own declarations, it may need ambient declarations for third-party dependencies or global augmentations.
Global Type Augmentation
Section titled “Global Type Augmentation”Extend browser globals with custom properties (e.g., analytics):
declare global { interface Window { HelixAnalytics?: { trackEvent(name: string, props: Record<string, unknown>): void; }; }}
export {};Usage in components:
private _handleClick(e: MouseEvent): void { // TypeScript now knows Window has HelixAnalytics window.HelixAnalytics?.trackEvent('hx-button:click', { variant: this.variant, });}Why export {}?
The empty export makes this a module file (not a script), ensuring TypeScript treats declare global as a module augmentation (not redeclaration).
Custom Element Registry Augmentation
Section titled “Custom Element Registry Augmentation”Type-safe custom element registration:
declare global { interface CustomElementRegistry { whenDefined(name: 'hx-button'): Promise<CustomElementConstructor>; whenDefined(name: 'hx-card'): Promise<CustomElementConstructor>; whenDefined(name: string): Promise<CustomElementConstructor>; }}
export {};Consumer benefit:
// TypeScript autocompletes 'hx-button', 'hx-card'await customElements.whenDefined('hx-button');Module Declaration (Third-Party Packages)
Section titled “Module Declaration (Third-Party Packages)”For packages without TypeScript definitions, create ambient module declarations:
// Example: Declare types for a CSS-in-JS library without typesdeclare module 'some-untyped-library' { export function css(template: TemplateStringsArray, ...values: unknown[]): string;}Package.json Type Exports
Section titled “Package.json Type Exports”The package.json exports field maps import paths to declaration files, ensuring TypeScript and bundlers resolve types correctly.
Exports Field Configuration
Section titled “Exports Field Configuration”{ "name": "@helixui/library", "type": "module", "main": "./dist/index.js", "module": "./dist/index.js", "types": "./dist/index.d.ts", "exports": { ".": { "types": "./dist/index.d.ts", "import": "./dist/index.js" }, "./components/*": { "types": "./dist/components/*/index.d.ts", "import": "./dist/components/*/index.js" }, "./custom-elements.json": "./custom-elements.json" }}How TypeScript uses this:
- Import
@helixui/library: TypeScript resolves todist/index.d.ts(viaexports["."].types) - Import
@helixui/library/components/hx-button: TypeScript resolves todist/components/hx-button/index.d.ts(via wildcard pattern) - Import
@helixui/library/custom-elements.json: No types (JSON file)
Conditional Exports
Section titled “Conditional Exports”The types condition takes precedence for TypeScript, while import handles runtime resolution:
{ "exports": { "./components/hx-button": { "types": "./dist/components/hx-button/index.d.ts", "import": "./dist/components/hx-button/index.js", "require": "./dist/components/hx-button/index.cjs" } }}Fallback order:
- TypeScript: Uses
typespath - ESM bundlers (Vite, Rollup): Use
importpath - CommonJS (Node.js): Use
requirepath (if provided)
Wildcard Pattern Gotchas
Section titled “Wildcard Pattern Gotchas”The wildcard "./components/*" expands to match any path:
// All resolve to dist/components/{name}/index.d.tsimport '@helixui/library/components/hx-button';import '@helixui/library/components/hx-card';import '@helixui/library/components/hx-nonexistent'; // Resolves, but fails at runtimeLimitation: TypeScript doesn’t validate that the component exists. If you typo a component name, you get a runtime error (module not found), not a compile-time error.
Type Checking Declaration Files
Section titled “Type Checking Declaration Files”After generating declarations, verify they match your public API and don’t contain errors.
Type Check Command
Section titled “Type Check Command”npm run type-checkThis runs tsc --noEmit, which:
- Checks all source files for type errors
- Validates generated
.d.tsfiles are well-formed - Ensures declaration file exports match source exports
Common Declaration Errors
Section titled “Common Declaration Errors”Missing Type Annotations
Section titled “Missing Type Annotations”// Source: Implicit return type (inferred as 'any')function getVariant() { return this.variant;}
// Declaration: 'any' type leaks into public APIgetVariant(): any;Fix: Always annotate public method return types:
function getVariant(): 'primary' | 'secondary' | 'ghost' { return this.variant;}Private Members Exposed
Section titled “Private Members Exposed”// Source: Missing 'private' modifier_internalState = false;
// Declaration: Exposed as public_internalState: boolean;Fix: Mark internal members as private or protected:
private _internalState = false;External Dependencies Not Declared
Section titled “External Dependencies Not Declared”// Source: Import from untyped packageimport { someUtil } from 'untyped-package';
// Declaration: Error - cannot find module 'untyped-package'Fix: Add ambient module declaration (see Ambient Declarations).
Best Practices for Declaration Files
Section titled “Best Practices for Declaration Files”1. Never Manually Edit Generated Declarations
Section titled “1. Never Manually Edit Generated Declarations”Declaration files are build artifacts. Editing them directly causes:
- Changes overwritten on next build
- Drift between source and declarations
- Merge conflicts in version control
Do this instead: Update source files and regenerate declarations.
2. Annotate All Public API Types
Section titled “2. Annotate All Public API Types”Explicit types prevent any leaks and improve IntelliSense:
// Good: Explicit types@property({ type: String })variant: 'primary' | 'secondary' | 'ghost' = 'primary';
focus(options?: FocusOptions): void { this._input?.focus(options);}
// Bad: Inferred types (may become 'any')@property({ type: String })variant = 'primary'; // Type: string (too broad)
focus(options?) { this._input?.focus(options); // Return type: void (correct, but implicit)}3. Use JSDoc for Documentation
Section titled “3. Use JSDoc for Documentation”JSDoc comments in source files are preserved in declarations and power IDE tooltips:
/** * Checks whether the input satisfies its constraints. * @returns `true` if valid, `false` otherwise. */checkValidity(): boolean { return this._internals.checkValidity();}4. Export Only Public API
Section titled “4. Export Only Public API”Avoid exporting internal utilities from the main entry point:
// Bad: Exports internal helperexport { helixButtonStyles } from './components/hx-button/hx-button.styles.js';
// Good: Only export component classexport { HelixButton } from './components/hx-button/hx-button.js';Internal exports pollute autocomplete and suggest non-public APIs to consumers.
5. Test Declarations Locally
Section titled “5. Test Declarations Locally”Before publishing, test that declarations work in a consumer project:
# In hx-librarynpm run buildnpm pack
# In test projectnpm install /path/to/helix-library-0.0.1.tgzVerify:
- Import paths resolve (
import '@helixui/library/components/hx-button') - Autocomplete works (
button.variantsuggests union values) - “Go to Definition” navigates to source (if declaration maps enabled)
6. Version Declarations with Source Code
Section titled “6. Version Declarations with Source Code”Declaration files must stay synchronized with JavaScript output. Never publish a version where:
.jsfiles are version 1.2.0.d.tsfiles are version 1.1.0
Use automated publishing workflows (changesets, semantic-release) to ensure versions stay aligned.
Troubleshooting Declaration Generation
Section titled “Troubleshooting Declaration Generation”Problem: No .d.ts Files Generated
Section titled “Problem: No .d.ts Files Generated”Symptom: npm run build completes, but dist/ contains no .d.ts files.
Cause: declaration not enabled in tsconfig.json.
Fix:
{ "compilerOptions": { "declaration": true }}Problem: Declaration Files Missing Exports
Section titled “Problem: Declaration Files Missing Exports”Symptom: Consumer imports fail with “Module has no exported member ‘HelixButton’”.
Cause: Source file doesn’t export the class, or exclude pattern hides the file.
Fix: Verify src/components/hx-button/index.ts exports the class:
export { HelixButton } from './hx-button.js';Check tsconfig.json doesn’t exclude the file:
{ "exclude": ["src/**/*.test.ts", "src/**/*.stories.ts"]}Problem: Declaration Map “Go to Definition” Doesn’t Work
Section titled “Problem: Declaration Map “Go to Definition” Doesn’t Work”Symptom: Clicking “Go to Definition” opens .d.ts file, not .ts source.
Cause: declarationMap: true not set, or source files not accessible.
Fix:
- Enable declaration maps:
{ "compilerOptions": { "declarationMap": true }}- Ensure source files are published (for npm packages) or accessible (for monorepos):
{ "files": [ "dist", "src" // Include source files for monorepo navigation ]}Problem: HTMLElementTagNameMap Not Working
Section titled “Problem: HTMLElementTagNameMap Not Working”Symptom: document.querySelector('hx-button') still returns HTMLElement | null.
Cause: Declaration file doesn’t include declare global augmentation.
Fix: Verify the component’s .d.ts file includes:
declare global { interface HTMLElementTagNameMap { 'hx-button': HelixButton; }}If missing, check source file includes it after the class definition.
Advanced: Multi-Entry Point Declaration Strategy
Section titled “Advanced: Multi-Entry Point Declaration Strategy”hx-library uses per-component entry points for tree-shaking. This requires careful declaration file organization to match JavaScript entry points.
Entry Point Structure
Section titled “Entry Point Structure”Each component has an index.ts re-export file:
export { HelixButton } from './hx-button.js';Generated declarations:
export { HelixButton } from './hx-button.js';//# sourceMappingURL=index.d.ts.mapimport { LitElement } from 'lit';
export declare class HelixButton extends LitElement { variant: 'primary' | 'secondary' | 'ghost'; // ...}
declare global { interface HTMLElementTagNameMap { 'hx-button': HelixButton; }}//# sourceMappingURL=hx-button.d.ts.mapWhy Two Declaration Files?
Section titled “Why Two Declaration Files?”index.d.ts: Entry point type (re-exports fromhx-button.d.ts)hx-button.d.ts: Implementation type (class definition)
This mirrors JavaScript output and allows:
- Direct class imports:
import { HelixButton } from '@helixui/library/components/hx-button'resolves toindex.d.ts - Deep imports (advanced):
import { HelixButton } from '@helixui/library/components/hx-button/hx-button'resolves tohx-button.d.ts
Package.json Mapping
Section titled “Package.json Mapping”The exports field maps both entry points:
{ "exports": { "./components/*": { "types": "./dist/components/*/index.d.ts", "import": "./dist/components/*/index.js" } }}TypeScript resolves @helixui/library/components/hx-button → dist/components/hx-button/index.d.ts → re-export from hx-button.d.ts.
References
Section titled “References”Official TypeScript documentation on declaration files and related features:
- TypeScript: Documentation - Type Declarations
- TypeScript: Documentation - Declaration Files Introduction
- TypeScript: Documentation - Modules .d.ts
- TypeScript: TSConfig Option: declaration
- TypeScript: TSConfig Option: declarationMap
- TypeScript: Documentation - Creating .d.ts Files from .js files
Additional resources on module augmentation and web component typing:
- Defining a component – Lit
- Module Augmentation in TypeScript - GeeksforGeeks
- TypeScript module augmentation for nested JavaScript files · Logto blog
Next Steps
Section titled “Next Steps”- Read Typing Lit Components for component-level type patterns
- Explore Packaging for Distribution for npm publishing workflow
- Review Strict Mode for TypeScript compiler settings