or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

analysis-correctness.mdconfigs.mdenvironment-specific.mdindex.mdmodule-systems.mdpath-resolution.mdstatic-analysis.mdstyle-organization.mdtypescript.md
tile.json

typescript.mddocs/

TypeScript Integration

ESLint Plugin Import X provides specialized rules and configurations for seamless TypeScript integration, including type-only import handling, consistent type specifier styles, and TypeScript-aware module resolution.

Type Import/Export Rules

consistent-type-specifier-style

Enforces consistent usage of type specifiers in import/export statements.

const consistentTypeSpecifierStyle: RuleModule<'typeOverValue' | 'valueOverType', [
  'prefer-inline' | 'prefer-top-level'
]>;

Options:

  • 'prefer-inline': Prefer inline type specifiers (import { type Foo })
  • 'prefer-top-level': Prefer top-level type imports (import type { Foo })

Example with prefer-inline:

// ✗ BAD - should use inline type specifiers
import type { User, UserConfig } from './types';
import { createUser, validateUser } from './types';

// ✓ GOOD - inline type specifiers  
import { type User, type UserConfig, createUser, validateUser } from './types';

Example with prefer-top-level:

// ✗ BAD - should separate type and value imports
import { type User, createUser } from './types';

// ✓ GOOD - separate type and value imports
import type { User } from './types';
import { createUser } from './types';

no-import-module-exports

Forbids mixing import declarations with module.exports (prevents TypeScript/CommonJS conflicts).

const noImportModuleExports: RuleModule<'notBothAllowed', [
  {
    exceptions?: string[];
  }?
]>;

Options:

  • exceptions (string[]): File patterns to exclude from this rule

Example:

// ✗ BAD - mixing ES imports with CommonJS exports
import React from 'react';
import { Component } from 'react';
module.exports = MyComponent;

// ✓ GOOD - consistent ES module syntax
import React, { Component } from 'react';
export default MyComponent;

// ✓ GOOD - consistent CommonJS syntax  
const React = require('react');
const { Component } = require('react');
module.exports = MyComponent;

TypeScript Configuration

typescript Config Preset

The TypeScript configuration preset provides optimal settings for TypeScript projects.

const typescript: PluginConfig = {
  settings: {
    'import-x/extensions': ['.ts', '.tsx', '.js', '.jsx'],
    'import-x/external-module-folders': ['node_modules', 'node_modules/@types'],
    'import-x/parsers': {
      '@typescript-eslint/parser': ['.ts', '.tsx', '.cts', '.mts']
    },
    'import-x/resolver': {
      node: {
        extensions: ['.ts', '.tsx', '.js', '.jsx']
      }
    }
  },
  rules: {
    'import-x/named': 'off' // TypeScript handles this at compile time
  }
};

Key Features:

  • Supports TypeScript file extensions (.ts, .tsx, .cts, .mts)
  • Includes @types packages in module resolution
  • Uses @typescript-eslint/parser for TypeScript files
  • Disables named rule (TypeScript compiler handles this)

Type-Only Import Patterns

Type Import Examples

// Type-only imports (don't affect runtime)
import type { User, Config } from './types';
import type { ComponentProps } from 'react';

// Mixed imports with inline type specifiers
import { type User, createUser, type Config } from './api';

// Re-exporting types
export type { User } from './types';
export type { ComponentProps } from 'react';

// Default type imports
import type React from 'react';
import type { default as Logger } from './logger';

Value vs Type Import Detection

The plugin automatically detects type-only imports and handles them appropriately:

// These imports affect the import order and dependency analysis differently
import type { TypeDef } from './types';     // Type-only
import { RuntimeValue } from './values';    // Runtime value
import { type TypeDef2, runtimeFn } from './mixed'; // Mixed

TypeScript Resolver Configuration

Node + TypeScript Resolver

{
  "import-x/resolver": {
    "typescript": {
      "alwaysTryTypes": true,
      "project": "./tsconfig.json"
    },
    "node": {
      "extensions": [".js", ".jsx", ".ts", ".tsx", ".d.ts"]
    }
  }
}

Path Mapping Support

// tsconfig.json
{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["src/*"],
      "@types/*": ["types/*"],
      "@utils/*": ["src/utils/*"]
    }
  }
}

// ESLint config
{
  "import-x/resolver": {
    "typescript": {
      "project": "./tsconfig.json"
    }
  }
}

Project References and Monorepos

TypeScript Project References

// For TypeScript project references
{
  "import-x/resolver": {
    "typescript": {
      "project": ["./tsconfig.json", "packages/*/tsconfig.json"]
    }
  }
}

Monorepo Configuration

// ESLint config for TypeScript monorepo
{
  "import-x/resolver": {
    "typescript": {
      "project": [
        "./tsconfig.json",
        "./packages/*/tsconfig.json",
        "./apps/*/tsconfig.json"
      ],
      "alwaysTryTypes": true
    }
  },
  "import-x/external-module-folders": [
    "node_modules",
    "node_modules/@types",
    "packages/*/node_modules/@types"
  ]
}

Declaration Files

.d.ts File Handling

// types.d.ts - declaration files are handled specially
declare module 'legacy-module' {
  export function legacyFn(): void;
}

declare global {
  interface Window {
    customProperty: string;
  }
}

// Usage - imports from declaration files
import { legacyFn } from 'legacy-module'; // Resolved via .d.ts

Type Definition Resolution

The plugin respects TypeScript's type resolution order:

  1. Relative .d.ts files
  2. @types/package-name packages
  3. package.json types/typings field
  4. index.d.ts in package root

Advanced TypeScript Features

Conditional Types and Template Literals

// The plugin understands complex TypeScript patterns
export type EventMap<T> = {
  [K in keyof T as `on${Capitalize<string & K>}`]: (value: T[K]) => void;
};

// Import/export of complex types
import type { EventMap } from './types';
export type { EventMap };

Module Augmentation

// Module augmentation is properly recognized
declare module 'express' {
  interface Request {
    user?: User;
  }
}

// Importing augmented modules
import express from 'express'; // Includes augmentations

TypeScript-Specific Types

interface TypeScriptResolver {
  alwaysTryTypes?: boolean;
  project?: string | string[];
  tsconfigRootDir?: string;
  extensions?: string[];
  moduleDirectory?: string[];
  conditionNames?: string[];
}

interface TypeImportInfo {
  isTypeOnly: boolean;
  isInlineType: boolean;
  isDefaultTypeImport: boolean;
  specifiers: TypeSpecifier[];
}

interface TypeSpecifier {
  name: string;
  isType: boolean;
  isDefault: boolean;
  alias?: string;
}

type TypeSpecifierStyle = 'prefer-inline' | 'prefer-top-level';

interface TypeScriptParserOptions {
  jsx?: boolean;
  useJSXTextNode?: boolean;
  project?: string | string[];
  tsconfigRootDir?: string;
  extraFileExtensions?: string[];
}

Common TypeScript Patterns

React with TypeScript

// Component prop types
import type { FC, ReactNode } from 'react';

interface ButtonProps {
  children: ReactNode;
  onClick: () => void;
  variant?: 'primary' | 'secondary';
}

const Button: FC<ButtonProps> = ({ children, onClick, variant = 'primary' }) => {
  return <button onClick={onClick} className={variant}>{children}</button>;
};

export default Button;
export type { ButtonProps };

API Client Types

// API types and runtime code separation
import type { User, CreateUserRequest, ApiResponse } from './types';
import { apiClient } from './client';

export async function createUser(data: CreateUserRequest): Promise<ApiResponse<User>> {
  return apiClient.post('/users', data);
}

export type { User, CreateUserRequest, ApiResponse };

Utility Type Libraries

// Type utility library
export type DeepPartial<T> = {
  [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
};

export type RequireOne<T, K extends keyof T = keyof T> = 
  K extends keyof T ? T & Required<Pick<T, K>> : never;

// Usage
import type { DeepPartial, RequireOne } from './type-utils';

Integration Best Practices

  1. Use the TypeScript preset: Always extend from plugin:import-x/typescript
  2. Configure path mapping: Set up TypeScript resolver with your tsconfig.json
  3. Separate type and value imports: Use consistent type specifier style
  4. Handle declaration files: Include .d.ts files in resolver extensions
  5. Monorepo support: Configure multiple TypeScript projects properly