False positive: sonarjs/no-then incorrectly flags Yup validation library usage

Description:
What language is this for?
TypeScript/JavaScript

Which rule?
sonarjs/no-then (“then” should not be used on non-promise objects)

Why do you believe it’s a false-positive?
The rule incorrectly flags the Yup validation library’s conditional validation methods (then and otherwise) as if they were Promise methods, when they are actually part of Yup’s documented API for conditional validation.

Are you using:

SonarQube Server / Community Edition (self-hosted)

How can we reproduce the problem?
Here’s a self-contained code snippet that triggers the false positive:

import * as yup from ‘yup’;

// This valid Yup syntax triggers sonarjs/no-then false positives
const schema = yup.object().shape({
// Example 1: Conditional validation with then/otherwise
filePath: yup.string().when(‘deviceType’, {
is: (val) => [‘FILE_READER’, ‘FILE_WRITER’].includes(val),
then: yup.string().required(‘File Path is required’),  // False positive here
otherwise: yup.string().notRequired().nullable(),      // False positive here
}),

// Example 2: Another conditional validation
port: yup.number().when(‘deviceType’, {
is: (val) => [‘TCP_SERVER’, ‘UDP_LISTENER’].includes(val),
then: yup.number().min(0).required(‘Port is required’),  // False positive here
otherwise: yup.number().notRequired().nullable(),        // False positive here
}),
});

export default schema;

Additional context:

Yup is a popular validation library with over 1.5 million weekly downloads

The .then() and .otherwise() methods are documented Yup features for conditional validation

The code context clearly shows this is schema definition code, not Promise handling

The rule should be able to detect when these methods are used as part of validation libraries vs actual Promise chains

Expected behavior: The rule should not flag Yup’s conditional validation methods as they are not Promise-related.

Hello @MariaFlorenciaP,

I’m afraid you will have to use eslint-disable directives for cases like this one. Technically, even if not a Promise, it behaves like one, as any object with a then method will be treated as promise-like by JavaScript’s async infrastructure. This is why TypeScript has the PromiseLike<T> type, which represents any object with a then method, not just Promise instances. It’s the basis for interoperability between different promise implementations.

This is why it’s generally considered bad practice to name a method then unless you’re actually implementing a promise-like interface.

1 Like