TypeScript linter that detects object types and interfaces used by only a single function
npm install forbid-junk-object-typesA TypeScript linter that detects object types and interfaces used by only a single function. This helps identify cases where developers create generic wrapper types that don't describe actual domain concepts, often to work around ESLint's max-params rule.
Developers sometimes "cheat" parameter count rules by creating single-use types:
``typescript
// Bad: Generic wrapper that doesn't describe the domain
interface ProductDetailsParams {
product: Product
user: User
onNavigate: (path: string) => void
dispatch: Dispatch
dimensions: Dimensions | null
onAddToCart: AddToCartFn
subscription: Subscription | null
}
const renderProductDetails = (params: ProductDetailsParams) => { ... }
`
This tool:
1. Analyzes TypeScript files using the TypeScript Compiler API
2. Detects object types/interfaces used by only one function
3. Reports violations with actionable domain modeling guidance
4. Supports JSON-based suppression for gradual adoption
5. Integrates into CI/CD pipelines with fast changed-files-only mode
`bash`
npm install forbid-junk-object-typesor
pnpm add forbid-junk-object-typesor
yarn add forbid-junk-object-types
`bashCheck all files in current directory
npx forbid-junk-object-types
$3
Add to your
package.json:`json
{
"scripts": {
"check-types": "forbid-junk-object-types",
"check-types:changed": "forbid-junk-object-types --changed-only"
}
}
`$3
-
--target-dir - Directory to analyze (default: current directory)
- --suppress-all - Generate suppressions for all violations
- --changed-only - Only check files changed vs origin/main (for CI)
- --files - Specific files to check
- --help, -h - Show help messageSuppression Mechanism
Suppressions are stored in
:`json
{
"src/apollo/client.ts": {
"MapsResultSetMergeOptions": {
"reason": "Apollo Client type policy requires this shape"
}
}
}
`What Gets Flagged
The tool flags object types/interfaces that:
- Are only used by a single function (in signature or body)
- Are not exported (public API types are allowed)
- Don't extend/implement other types (polymorphism is allowed)
- Don't end with
*Props (React component props pattern - temporary exception)False Positives
The tool automatically allows:
- Exported types (may be used by other modules)
- Types in inheritance hierarchies
- React component props (
*Props suffix)
- Types used by multiple functionsCI Integration
$3
`yaml
name: CI
on: [push, pull_request]jobs:
junk-object-types:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Required for --changed-only
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm ci
- name: Check for junk object types (changed files only)
run: npx forbid-junk-object-types --changed-only
`$3
The tool uses standard exit codes:
-
0 - No violations found
- 1 - Violations found
- 2 - Error occurredDevelopment
`bash
Install dependencies
pnpm installBuild
pnpm run buildRun tests
pnpm testRun linter
pnpm run lint
`Philosophy
Single-use types often indicate missing domain modeling. Instead of creating generic wrappers like
Options, Config, or *Params, consider:1. Inline the parameters - If it's truly a one-off, just use individual parameters
2. Create a domain concept - Name the type after what it represents in your domain
$3
`typescript
// ✗ Generic wrapper
interface SearchOptions {
query: string
page: number
}// ✓ Domain concept
interface SearchQuery {
query: string
page: number
}
// ✓ Or inline if truly one-off
function search(query: string, page: number) { ... }
``MIT
Contributions are welcome! Please open an issue or submit a pull request on GitHub.