gund / eslint-plugin-deprecation

ESLint rule that reports usage of deprecated code

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

False Positive error when extending a deprecated method

dkimmich-onventis opened this issue · comments

In the following scenario, when calling method() on an instance of the New class, the plugin should not report an error, but it does:

class Old {
  /** @deprecated */
  method(): void {
  }
}

class New extends Old {
  method(): void {
  }
}

new Old().method(); // should throw an error -> everything fine
new New().method(); // should not throw an error -> still throws an error

I'm facing a similar issue where a function has multiple signatures, one of which is deprecated and even if I use the new calling convention I get a warning.

// From "fast-check" package

/**
 * @deprecated
 */
declare function lorem(maxWordsCount: number, sentencesMode: boolean): Arbitrary<string>;

declare function lorem(constraints: LoremConstraints): Arbitrary<string>;
import * as fc from "fast-check"

fc.lorem({ maxCount: 5 }) // <- warning issued here.

@wereHamster I cannot reproduce this. For me, everything works fine:

/**
 * @deprecated
 */
declare function lorem(maxWordsCount: number, sentencesMode: boolean): string;
declare function lorem(constraints: { maxCount: number }): string;

lorem({ maxCount: 5 }); // -> no warning
lorem(5, false); // -> warning

Are you sure the lint error is reported by this package? I ran into a very similar issue using eslint-plugin-import import-js/eslint-plugin-import#1532, which made me switch to this package.

Both vscode and eslint cli report the warning:

image

I'm using the latest eslint and related packages (@typescript-eslint/* etc).

We just released an updated with latest deps in v1.3.1 maybe you can try it out and see if this is still an issue?

@Delagen unfortunately this is still an issue with the latest version.

@json-derulo tried to fix this in Delagen#1, but I reverted it by his opinion about false positives Delagen#1 (comment). May be someone try to fix this? PR are welcome

Yes I tried to fix it, but it turned out to be way more complex than expected. I did not succeed to fix this.

What I observed is that the unit tests don't cover every case. I've updated them while trying to fix the issue, opened #42 to add them.

I've been able to narrow down the issue. With TypeScript 4.1 it works, since TypeScript 4.2 the described case is broken. Maybe due to their new feature abstract Construct Signatures. But had no luck so far finding out what needs to be changed in this repo.

Any updates on this? Facing same exact issue.

Angular 12
"@typescript-eslint/eslint-plugin": "^5.12.0",
"eslint": "^7.32.0",
"eslint-plugin-deprecation": "^1.3.2",
"typescript": "^4.3.5",

Similar issue with MockInstance.scope() from ngMocks in an Angular-project.

/**
 * This signature of MockInstance lets customize the instances of mock classes with a callback.
 * You can return a shape or change the instance.
 *
 * @deprecated please pass the callback directly instead of config.
 * @see https://ng-mocks.sudo.eu/api/MockInstance
 *
 * ```ts
 * MockInstance(ArbitraryComponent, {
 *   init: (instance, injector) => {
 *     instance.enabled = true;
 *     instance.db = injector.get(DatabaseService);
 *   },
 * });
 * MockInstance(ArbitraryDirective, {
 *   init: () => {
 *     return {
 *       someProperty: true,
 *     };
 *   },
 * });
 * ```
 */
export declare function MockInstance<T>(declaration: AnyType<T>, config?: {
	init?: (instance: T, injector: Injector | undefined) => void | Partial<T>;
}): void;
/**
 * Interface describes how to configure scopes for MockInstance.
 *
 * @see https://ng-mocks.sudo.eu/api/MockInstance#customization-scopes
 */
export declare namespace MockInstance {
	/**
	 * Creates a scope which remembers all future customizations of MockInstance.
	 * It allows to reset them afterwards.
	 *
	 * @see https://ng-mocks.sudo.eu/api/MockInstance#remember
	 */
	function remember(): void;
	/**
	 * Resets all changes in the current scope.
	 *
	 * @see https://ng-mocks.sudo.eu/api/MockInstance#restore
	 */
	function restore(): void;
	/**
	 * Creates a local scope in `beforeEach` and `afterEach`.
	 * If `suite` has been passed, then `beforeAll` and `afterAll` are used.
	 *
	 * @see https://ng-mocks.sudo.eu/api/MockInstance#scope
	 */
	function scope(scope?: "all" | "suite" | "case"): void;
}

Getting the following error message when using MockInstance.scope():

error  'MockInstance' is deprecated. please pass the callback directly instead of config  deprecation/deprecation

Here is a test-case which is currently failing:

    getValidTestCase(`
      /** @deprecated */ function Test(param: number): void;
      declare namespace Test {
        function any(): void;
      }
      Test.any();
    `),

I've encountered the same issue while updating faker. In my case, the problem is that faker is using TypeScript's function overload to type the signature of some methods. Some overloads are valid, while others are deprecated. Something like this:

foo(value: number): void;
/**
 * @deprecated use numeric inputs instead
 */
foo(value: string): void;

In this case, foo(1) is valid while foo('1') is deprecated.

I believe ESLint can't correctly handle this use case. Imagine this code:

foo(value);

Is value a number or a string? We can only know if we're at runtime or if we start integrating heavily with TypeScript.

In cases like this, where there's a function overload, and only some of the declarations are deprecated, I suggest this plugin ignores the code altogether.


For an example of a real-world failing code see https://github.com/faker-js/faker/blob/293f12741acb188fd8c7d9d6b3dc2dd9b52d4214/src/modules/date/index.ts#L70-L190

@Gpx it seems like your issue (overloaded functions/methods) is different from this one (extended class methods) so I would suggest you to go ahead and create a separate issue for it.