Skip to content

linter: vitest/require-mock-type-parameters false positive with 2+ chained mockResolvedValueOnce calls #21992

@ryan-sigma

Description

@ryan-sigma

What version of Oxlint are you using?

latest

What command did you run?

No response

What does your .oxlintrc.json (or oxlint.config.ts) config file look like?

No response

What happened?

The rule incorrectly fires when vi.fn() is chained with two or more mock calls.

// ✅ passes (1 mock call)
const a = vi.fn<() => Promise<string>>().mockResolvedValueOnce('a');

// ❌ false positive (2 mock calls — type param IS present)
const b = vi.fn<() => Promise<string>>()
  .mockResolvedValueOnce('a')
  .mockResolvedValueOnce('b');
The rule appears to treat the outermost call in the chain (.mockResolvedValueOnce) as the mock function call requiring type parameters, rather than vi.fn.

https://playground.oxc.rs/?lintRules=vitest%2Frequire-mock-type-parameters&options=%7B%22run%22%3A%7B%22lint%22%3Atrue%2C%22formatter%22%3Afalse%2C%22transform%22%3Afalse%2C%22isolatedDeclarations%22%3Afalse%2C%22whitespace%22%3Afalse%2C%22mangle%22%3Afalse%2C%22compress%22%3Afalse%2C%22scope%22%3Atrue%2C%22symbol%22%3Atrue%2C%22cfg%22%3Afalse%7D%2C%22parser%22%3A%7B%22extension%22%3A%22tsx%22%2C%22allowReturnOutsideFunction%22%3Atrue%2C%22preserveParens%22%3Atrue%2C%22allowV8Intrinsics%22%3Atrue%2C%22semanticErrors%22%3Atrue%7D%2C%22linter%22%3A%7B%7D%2C%22formatter%22%3A%7B%22useTabs%22%3Afalse%2C%22tabWidth%22%3A2%2C%22endOfLine%22%3A%22lf%22%2C%22printWidth%22%3A80%2C%22singleQuote%22%3Afalse%2C%22jsxSingleQuote%22%3Afalse%2C%22quoteProps%22%3A%22as-needed%22%2C%22trailingComma%22%3A%22all%22%2C%22semi%22%3Atrue%2C%22arrowParens%22%3A%22always%22%2C%22bracketSpacing%22%3Atrue%2C%22bracketSameLine%22%3Afalse%2C%22objectWrap%22%3A%22preserve%22%2C%22singleAttributePerLine%22%3Afalse%7D%2C%22transformer%22%3A%7B%22target%22%3A%22es2015%22%2C%22useDefineForClassFields%22%3Atrue%2C%22experimentalDecorators%22%3Atrue%2C%22emitDecoratorMetadata%22%3Atrue%2C%22optimizeEnums%22%3Atrue%2C%22optimizeConstEnums%22%3Atrue%7D%2C%22isolatedDeclarations%22%3A%7B%22stripInternal%22%3Afalse%7D%2C%22codegen%22%3A%7B%22normal%22%3Atrue%2C%22jsdoc%22%3Atrue%2C%22annotation%22%3Atrue%2C%22legal%22%3Atrue%7D%2C%22compress%22%3A%7B%7D%2C%22mangle%22%3A%7B%22topLevel%22%3Atrue%2C%22keepNames%22%3Afalse%7D%2C%22controlFlow%22%3A%7B%22verbose%22%3Afalse%7D%2C%22inject%22%3A%7B%22inject%22%3A%7B%7D%7D%2C%22define%22%3A%7B%22define%22%3A%7B%7D%7D%7D&code=%0A%0Aconst+r0+%3D+vi.fn%3C%28%29+%3D%3E+Promise%3Cstring+%7C+null%3E%3E%28%29%3B%0A%0Aconst+r1+%3D+vi.fn%3C%28%29+%3D%3E+Promise%3Cstring+%7C+null%3E%3E%28%29%0A++.mockResolvedValueOnce%28%27a%27%29%3B%0A%0Aconst+r2+%3D+vi.fn%3C%28%29+%3D%3E+Promise%3Cstring+%7C+null%3E%3E%28%29%0A++.mockResolvedValueOnce%28%27a%27%29%0A++.mockResolvedValueOnce%28%27b%27%29%3B%0A%0Aconst+r3+%3D+vi.fn%28%29%3B%0A

Metadata

Metadata

Assignees

Labels

Type

Priority

None yet

Effort

None yet

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions