@typescript-eslint/prefer-reduce-type-parameter

Require a type argument on reduce instead of a type assertion on the initial value

fixableneeds types

Also called typescript-eslint/prefer-reduce-type-parameter, typescript/prefer-reduce-type-parameter

reduce takes its result type from the initial value, and {} or [] alone gives you a type that's too narrow. {} as Record<string, number> fixes that, but an assertion also accepts a value that doesn't fit the type. reduce<Record<string, number>>(..., {}) gives you the same result type, and TypeScript still checks the initial value against it.

Only arrays and tuples are checked. If the value can't be assigned to the asserted type, you need the assertion and the call is left alone.

--fix moves the type from the assertion to the call.

Configure#

Off by default. This rule needs types, so turning it on makes bun lint type check your code first.

bunfig.toml
[lint.rules]
"@typescript-eslint/prefer-reduce-type-parameter" = "error" # or "warn"

Examples#

example.ts2 problems
function count(words: string[]) {
  return words.reduce((counts, word) => {
    counts[word] = (counts[word] ?? 0) + 1;
    return counts;
  }, {} as Record<string, number>);
}

function lengths(words: string[]) {
  return words.reduce((result, word) => result.concat(word.length), [] as number[]);
}
example.tsNo problems
function count(words: string[]) {
  return words.reduce<Record<string, number>>((counts, word) => {
    counts[word] = (counts[word] ?? 0) + 1;
    return counts;
  }, {});
}

function lengths(words: string[]) {
  return words.reduce<number[]>((result, word) => result.concat(word.length), []);
}

Here {} isn't a valid Summary, so moving the type would be a type error:

example.tsNo problems
interface Summary {
  longest: string;
}

function summarize(words: string[]) {
  return words.reduce((summary, word) => {
    summary.longest = word;
    return summary;
  }, {} as Summary);
}