Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[@typescript-eslint/no-unused-vars] False positive for an interface used as a generic parameter on a function with a decorator. #2961

Closed
3 tasks done
timecatalyst opened this issue Jan 21, 2021 · 9 comments
Labels
duplicate This issue or pull request already exists package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin

Comments

@timecatalyst
Copy link

timecatalyst commented Jan 21, 2021

Sorry, I know a lot of similar issues like this have been reported, but none of them appear to address my specific problem. I'm working in a fresh NestJS project (generated using @nestjs/cli) and for some reason the @Get() decorator is causing the linter to flag an interface as being unused.

I had originally reported the issue on the NestJS repo, but they suggested it may be a linter problem and to ask about it here (See my comment near the bottom: nestjs/nest#4684). I accept the possibility that I might just have something wrong in my configuration, but I can't for the life of me figure out what that may be.

  • I have tried restarting my IDE and the issue persists.
  • I have updated to the latest version of the packages.
  • I have read the FAQ and my problem is not listed.

Repro

{
  "rules": {
    "@typescript-eslint/interface-name-prefix": "off",
    "@typescript-eslint/explicit-function-return-type": "off",
    "@typescript-eslint/explicit-module-boundary-types": "off",
    "@typescript-eslint/no-explicit-any": "off",
  },
};

As I mentioned earlier, this is a brand new project generated freshly from the NestJS CLI. The only upgrade the @typescript-eslint libraries to the latest versions.

The linter generates a warning on the interface Foo at line 3, despite its use at line 10.

If I remove the @Get() decorator, or rewrite doSomething() to not use a Promise<>, the warning goes away.

 1 import { Controller, Get } from '@nestjs/common';
 2
 3 interface Foo {
 4   foo: string;
 5 }
 6
 7 @Controller('foo') 
 8 export class FooController {
 9   @Get()
10   async doSomething(): Promise<Foo> {
11     return Promise.resolve({ foo: 'bar' });
12   }
13 }

Screen Shot 2021-01-21 at 11 19 45 AM

tsconfig.json:

{
  "compilerOptions": {
    "module": "commonjs",
    "declaration": true,
    "removeComments": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "allowSyntheticDefaultImports": true,
    "target": "es2017",
    "sourceMap": true,
    "outDir": "./dist",
    "baseUrl": "./",
    "incremental": true
  }
}

Expected Result

No warning should occur.

Actual Result

ESLint: 'Foo' is defined but never used.(@typescript-eslint/no-unused-vars)

Additional Info

None

Versions

package version
@typescript-eslint/eslint-plugin 4.14.0
@typescript-eslint/parser 4.14.0
TypeScript 4.0.5
ESLint 7.12.1
node 12.8.3
@timecatalyst timecatalyst added package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin triage Waiting for maintainers to take a look labels Jan 21, 2021
@bradzacher
Copy link
Member

Same as #2941, #2942, #2945, #2947, #2950, #2957

@timecatalyst
Copy link
Author

Sorry, but I'm still seeing the same problem after upgrading my libraries to v4.14.1. Same reproduction steps as before, a class method decorator combined with a generic return type. Here's a more minimalistic version that removes NestJS from the equation:

 1 interface Foo {
 2   foo: string;
 3 }
 4
 5 function MyDecorator() {
 6   return (target, propertyKey: string, descriptor: PropertyDescriptor) =>
 7     console.log('MyDecorator(): called');
 8 }
 9
10 export class FooController {
11   @MyDecorator()
12   async doSomething(): Promise<Foo> {
13     return Promise.resolve({ foo: 'foo' });
14   }
15 }

Screen Shot 2021-01-25 at 3 18 34 PM

@bradzacher
Copy link
Member

Nuke your node modules and reinstall.
Also restart your IDE.

This is fixed (I just tested your code against master)

@timecatalyst
Copy link
Author

Yeah, I've nuked node modules and restarted my IDE several times to no avail. I suppose it's possible something might be conflicting with it, but I'm not sure what that would be at this point. Here are my deps:

 "dependencies": {
    "@nestjs/common": "^7.5.1",
    "@nestjs/core": "^7.5.1",
    "@nestjs/platform-express": "^7.5.1",
    "reflect-metadata": "^0.1.13",
    "rimraf": "^3.0.2",
    "rxjs": "^6.6.3"
  },
  "devDependencies": {
    "@nestjs/cli": "^7.5.1",
    "@nestjs/schematics": "^7.1.3",
    "@nestjs/testing": "^7.5.1",
    "@types/express": "^4.17.8",
    "@types/jest": "^26.0.15",
    "@types/node": "^14.14.6",
    "@types/supertest": "^2.0.10",
    "@typescript-eslint/eslint-plugin": "^4.14.1",
    "@typescript-eslint/parser": "^4.14.1",
    "eslint": "^7.18.0",
    "eslint-config-prettier": "7.1.0",
    "eslint-plugin-jsx-a11y": "^6.4.1",
    "eslint-plugin-prettier": "^3.1.4",
    "jest": "^26.6.3",
    "prettier": "^2.1.2",
    "supertest": "^6.0.0",
    "ts-jest": "^26.4.3",
    "ts-loader": "^8.0.14",
    "ts-node": "^9.1.1",
    "tsconfig-paths": "^3.9.0",
    "typescript": "^4.1.3"
  },

@bradzacher
Copy link
Member

There may be multiple versions installed?
https://github.com/typescript-eslint/typescript-eslint/blob/master/docs/getting-started/linting/FAQ.md#how-do-i-check-to-see-what-versions-are-installed

Hard to say exactly - it all depends on your project setup.

@timecatalyst
Copy link
Author

Looks like I'm on the right version. I'm going to try to build the project up from scratch and see where it gets me. I'll post back if I find anything. Thanks for the feedback.

% yarn list @typescript-eslint/eslint-plugin @typescript-eslint/parser
yarn list v1.22.10
warning Filtering by arguments is deprecated. Please use the pattern option instead.
├─ @typescript-eslint/eslint-plugin@4.14.1
└─ @typescript-eslint/parser@4.14.1
✨  Done in 0.33s.

@timecatalyst
Copy link
Author

Okay, I rebuild the project with just typescript and linting:

package.json:
{
  "name": "eslint-test",
  "version": "0.0.1",
  "description": "",
  "author": "",
  "private": true,
  "license": "UNLICENSED",
  "scripts": {},
  "dependencies": {},
  "devDependencies": {
    "@types/node": "^14.14.22",
    "@typescript-eslint/eslint-plugin": "^4.14.1",
    "@typescript-eslint/parser": "^4.14.1",
    "eslint": "^7.18.0",
    "eslint-config-prettier": "^7.2.0",
    "eslint-plugin-prettier": "^3.3.1",
    "prettier": "^2.2.1",
    "ts-loader": "^8.0.14",
    "ts-node": "^9.1.1",
    "tsconfig-paths": "^3.9.0",
    "typescript": "^4.1.3"
  }
}

tsconfig.json:
{
  "compilerOptions": {
    "module": "commonjs",
    "declaration": true,
    "removeComments": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "allowSyntheticDefaultImports": true,
    "target": "es2017",
    "sourceMap": true,
    "outDir": "./dist",
    "baseUrl": "./",
    "incremental": true
  }
}

I have a single index.ts containing the same test code from before.

Using only the above files, I did not receive a warning on interface Foo. But, when I added in the .eslintrc.js file from the NestJS repo, the warning reappeared. I did some digging and found that removing plugin:@typescript-eslint/recommended from the extends array makes the warning disappear (along with other legitimate no-unused-vars warnings). I suspect there may be some invalid usage going on. Here's the eslintrc:

module.exports = {
  parser: '@typescript-eslint/parser',
  parserOptions: {
    project: 'tsconfig.json',
    sourceType: 'module',
  },
  plugins: ['@typescript-eslint/eslint-plugin'],
  extends: [
    'plugin:@typescript-eslint/eslint-recommended',
    'plugin:@typescript-eslint/recommended',
    'plugin:@typescript-eslint/recommended-requiring-type-checking',
    'prettier/@typescript-eslint',
    'plugin:prettier/recommended',
  ],
  root: true,
  env: {
    node: true,
    jest: true,
  },
  ignorePatterns: ['.eslintrc.js'],
  rules: {
    '@typescript-eslint/interface-name-prefix': 'off',
    '@typescript-eslint/explicit-function-return-type': 'off',
    '@typescript-eslint/explicit-module-boundary-types': 'off',
    '@typescript-eslint/no-explicit-any': 'off',
  },
};

@timecatalyst
Copy link
Author

@bradzacher I think I found the culprit: "emitDecoratorMetadata": true, in tsconfig.json. If I remove that key, or set the value to false, the linter error disappears.

@bradzacher
Copy link
Member

See #2972

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Feb 26, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
duplicate This issue or pull request already exists package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin
Projects
None yet
Development

No branches or pull requests

2 participants