@mckabue/no-same-type-params
v1.0.1
Published
ESLint rule that disallows consecutive function parameters sharing the same type annotation. Encourages refactoring to object parameters.
Maintainers
Readme
@mckabue/no-same-type-params
An ESLint rule that disallows consecutive function parameters sharing the same type annotation.
The Problem
Functions with multiple consecutive parameters of the same type are error-prone. Callers can easily swap arguments without any compiler warning:
// 😱 Which string is source? Which is dest? Easy to mix up!
function copy(source: string, dest: string, adapterId: string) { ... }
// Swapped source and dest — no TypeScript error!
copy(destPath, sourcePath, adapterId);The Solution
This rule catches these signatures and encourages refactoring to object parameters:
// ✅ Clear, self-documenting, impossible to swap
function copy({ source, dest, adapterId }: CopyParams) { ... }
copy({ source: sourcePath, dest: destPath, adapterId });Installation
npm install @mckabue/no-same-type-params --save-dev
# or
yarn add @mckabue/no-same-type-params --dev
# or
pnpm add @mckabue/no-same-type-params --save-devPeer Dependencies:
eslint: >=8.0.0
You'll also need @typescript-eslint/parser for TypeScript support.
Usage
ESLint Flat Config (eslint.config.js)
import noSameTypeParams from '@mckabue/no-same-type-params';
import * as tsParser from '@typescript-eslint/parser';
export default [
{
files: ['**/*.ts', '**/*.tsx'],
languageOptions: {
parser: tsParser,
},
plugins: {
'@mckabue': {
rules: {
'no-same-type-params': noSameTypeParams,
},
},
},
rules: {
'@mckabue/no-same-type-params': 'warn',
},
},
];Legacy Config (.eslintrc)
{
"plugins": ["@mckabue"],
"rules": {
"@mckabue/no-same-type-params": "warn"
}
}Examples
❌ Invalid (triggers warning)
// Two consecutive string params
const fn = (a: string, b: string) => {};
// Three consecutive string params (2 warnings)
function copy(source: string, dest: string, adapterId: string) {}
// Default values with same types
const fn = (a: string = 'x', b: string = 'y') => {};
// Same array types
const fn = (a: string[], b: string[]) => {};
// Same union types
const fn = (a: string | number, b: string | number) => {};✅ Valid (no warnings)
// Different types
const fn = (a: string, b: number) => {};
// Object parameter
const fn = (opts: { source: string; dest: string }) => {};
// Non-consecutive same types (different type in between)
const fn = (a: string, b: number, c: string) => {};
// Untyped parameters (can't compare)
const fn = (a, b) => {};
// Single parameter
const fn = (a: string) => {};How It Works
The rule inspects FunctionDeclaration, FunctionExpression, and ArrowFunctionExpression nodes. For each pair of consecutive parameters:
- Extracts the TypeScript type annotation (handles
Identifier,AssignmentPattern, andRestElement) - Compares the source text of both type annotations
- Reports if they match
Untyped parameters are ignored — only TypeScript-annotated parameters are compared.
License
MIT © Kabui Charles
