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

[dot-notation] False positive with optional chaining and allowIndexSignaturePropertyAccess: true #3510

Closed
3 tasks done
kohlmannj opened this issue Jun 9, 2021 · 2 comments · Fixed by #3711
Closed
3 tasks done
Labels
bug Something isn't working package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin

Comments

@kohlmannj
Copy link

kohlmannj commented Jun 9, 2021

  • 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

{
  "parser": "@typescript-eslint/parser",
  "parserOptions": {
    "project": "tsconfig.json"
  },
  "plugins": ["@typescript-eslint"],
  "rules": {
    "@typescript-eslint/dot-notation": [
      "error",
      {
        "allowIndexSignaturePropertyAccess": true
      }
    ]
  }
}
interface Nested {
  property: string;

  [key: string]: number | string;
}

interface Dingus {
  nested: Nested;
}

let dingus: Dingus | undefined;

dingus?.nested.property;
dingus?.nested['hello'];
{
  "compilerOptions": {
    /* Basic Options */
    "lib": ["DOM", "DOM.Iterable", "ES2020"],
    "module": "ES2020",
    "target": "ES2020",

    /* Module Resolution Options */
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "esModuleInterop": true,
    "preserveSymlinks": true,

    /* Experimental Options */
    "experimentalDecorators": true,

    /* Advanced Options */
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true,

    /* Strict Type-Checking Options */
    "strict": true,

    /* Additional Checks */
    "noFallthroughCasesInSwitch": true,
    "noImplicitReturns": true,
    "noPropertyAccessFromIndexSignature": true,
    "noUncheckedIndexedAccess": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,

    /* Incremental Build Options */
    "incremental": true,

    "baseUrl": "src",
    "noEmit": true
  }
}

Expected Result

The test TS code does not contain any ESLint errors.

Actual Result

The last line of the test TS code, dingus?.nested['hello'];, has this ESLint error:

["hello"] is better written in dot notation. eslint(typescript-eslint/dot-notation)

Additional Info

This GitHub repo contains this same test code and configs: https://github.com/kohlmannj/typescript-eslint-dot-notation-index-access-optional-chaining-bug

This is a reproduction of the issue that @eugene-stativka noted here: #3361 (comment)

Relates to:

Output from eslint --ext ".ts" src --debug

Note: You can rerun this command in https://github.com/kohlmannj/typescript-eslint-dot-notation-index-access-optional-chaining-bug with the yarn lint:debug script.

➜  typescript-eslint-dot-notation-index-access-optional-chaining-bug git:(main) ✗ yarn lint:debug
yarn run v1.22.10
$ yarn lint  --debug
$ eslint --ext ".ts" src --debug
  eslint:cli CLI args: [ '--ext', '.ts', 'src', '--debug' ] +0ms
  eslint:cli Running on files +4ms
  eslintrc:config-array-factory Loading JSON config file: /Users/joseph/Sites/kohlmannj/typescript-eslint-dot-notation-index-access-optional-chaining-bug/package.json +0ms
  eslintrc:ignore-pattern Create with: [ IgnorePattern { patterns: [ '/**/node_modules/*' ], basePath: '/Users/joseph/Sites/kohlmannj/typescript-eslint-dot-notation-index-access-optional-chaining-bug', loose: false } ] +0ms
  eslintrc:ignore-pattern   processed: { basePath: '/Users/joseph/Sites/kohlmannj/typescript-eslint-dot-notation-index-access-optional-chaining-bug', patterns: [ '/**/node_modules/*' ] } +1ms
  eslintrc:ignore-pattern Create with: [ IgnorePattern { patterns: [ '/**/node_modules/*' ], basePath: '/Users/joseph/Sites/kohlmannj/typescript-eslint-dot-notation-index-access-optional-chaining-bug', loose: false } ] +1ms
  eslintrc:ignore-pattern   processed: { basePath: '/Users/joseph/Sites/kohlmannj/typescript-eslint-dot-notation-index-access-optional-chaining-bug', patterns: [ '/**/node_modules/*' ] } +0ms
  eslint:file-enumerator Start to iterate files: [ 'src' ] +0ms
  eslint:file-enumerator Directory: /Users/joseph/Sites/kohlmannj/typescript-eslint-dot-notation-index-access-optional-chaining-bug/src +1ms
  eslint:file-enumerator Enter the directory: /Users/joseph/Sites/kohlmannj/typescript-eslint-dot-notation-index-access-optional-chaining-bug/src +0ms
  eslintrc:cascading-config-array-factory Load config files for /Users/joseph/Sites/kohlmannj/typescript-eslint-dot-notation-index-access-optional-chaining-bug/src. +0ms
  eslintrc:cascading-config-array-factory No cache found: /Users/joseph/Sites/kohlmannj/typescript-eslint-dot-notation-index-access-optional-chaining-bug/src. +0ms
  eslintrc:config-array-factory Config file not found on /Users/joseph/Sites/kohlmannj/typescript-eslint-dot-notation-index-access-optional-chaining-bug/src +5ms
  eslintrc:cascading-config-array-factory No cache found: /Users/joseph/Sites/kohlmannj/typescript-eslint-dot-notation-index-access-optional-chaining-bug. +1ms
  eslintrc:config-array-factory Loading legacy config file: /Users/joseph/Sites/kohlmannj/typescript-eslint-dot-notation-index-access-optional-chaining-bug/.eslintrc +0ms
  eslintrc:config-array-factory Config file found: /Users/joseph/Sites/kohlmannj/typescript-eslint-dot-notation-index-access-optional-chaining-bug/.eslintrc +19ms
  eslintrc:config-array-factory Loading parser "@typescript-eslint/parser" from /Users/joseph/Sites/kohlmannj/typescript-eslint-dot-notation-index-access-optional-chaining-bug/.eslintrc +1ms
  eslintrc:config-array-factory Loaded: @typescript-eslint/parser@4.26.1 (/Users/joseph/Sites/kohlmannj/typescript-eslint-dot-notation-index-access-optional-chaining-bug/node_modules/@typescript-eslint/parser/dist/index.js) +1ms
  eslintrc:config-array-factory Loading plugin "@typescript-eslint" from /Users/joseph/Sites/kohlmannj/typescript-eslint-dot-notation-index-access-optional-chaining-bug/.eslintrc +239ms
  eslintrc:config-array-factory Loaded: @typescript-eslint/eslint-plugin@4.26.1 (/Users/joseph/Sites/kohlmannj/typescript-eslint-dot-notation-index-access-optional-chaining-bug/node_modules/@typescript-eslint/eslint-plugin/dist/index.js) +1ms
  eslintrc:config-array-factory Plugin /Users/joseph/Sites/kohlmannj/typescript-eslint-dot-notation-index-access-optional-chaining-bug/node_modules/@typescript-eslint/eslint-plugin/dist/index.js loaded in: 152ms +152ms
  eslintrc:cascading-config-array-factory No cache found: /Users/joseph/Sites/kohlmannj. +413ms
  eslintrc:config-array-factory Config file not found on /Users/joseph/Sites/kohlmannj +0ms
  eslintrc:cascading-config-array-factory No cache found: /Users/joseph/Sites. +0ms
  eslintrc:config-array-factory Config file not found on /Users/joseph/Sites +0ms
  eslintrc:cascading-config-array-factory No cache found: /Users/joseph. +0ms
  eslintrc:cascading-config-array-factory Stop traversing because of considered root. +0ms
  eslintrc:cascading-config-array-factory Configuration was determined: ConfigArray(2) [ { type: 'config', name: 'DefaultIgnorePattern', filePath: '', criteria: null, env: undefined, globals: undefined, ignorePattern: IgnorePattern { patterns: [Array], basePath: '/Users/joseph/Sites/kohlmannj/typescript-eslint-dot-notation-index-access-optional-chaining-bug', loose: false }, noInlineConfig: undefined, parser: undefined, parserOptions: undefined, plugins: undefined, processor: undefined, reportUnusedDisableDirectives: undefined, root: undefined, rules: undefined, settings: undefined }, { type: 'config', name: '.eslintrc', filePath: '/Users/joseph/Sites/kohlmannj/typescript-eslint-dot-notation-index-access-optional-chaining-bug/.eslintrc', criteria: null, env: undefined, globals: undefined, ignorePattern: undefined, noInlineConfig: undefined, parser: { error: null, filePath: '/Users/joseph/Sites/kohlmannj/typescript-eslint-dot-notation-index-access-optional-chaining-bug/node_modules/@typescript-eslint/parser/dist/index.js', id: '@typescript-eslint/parser', importerName: '.eslintrc', importerPath: '/Users/joseph/Sites/kohlmannj/typescript-eslint-dot-notation-index-access-optional-chaining-bug/.eslintrc' }, parserOptions: { project: 'tsconfig.json' }, plugins: { '@typescript-eslint': [Object] }, processor: undefined, reportUnusedDisableDirectives: undefined, root: undefined, rules: { '@typescript-eslint/dot-notation': [Array] }, settings: undefined } ] on /Users/joseph/Sites/kohlmannj/typescript-eslint-dot-notation-index-access-optional-chaining-bug/src +2ms
  eslintrc:ignore-pattern Create with: [ IgnorePattern { patterns: [ '/**/node_modules/*' ], basePath: '/Users/joseph/Sites/kohlmannj/typescript-eslint-dot-notation-index-access-optional-chaining-bug', loose: false } ] +418ms
  eslintrc:ignore-pattern   processed: { basePath: '/Users/joseph/Sites/kohlmannj/typescript-eslint-dot-notation-index-access-optional-chaining-bug', patterns: [ '/**/node_modules/*' ] } +0ms
  eslintrc:ignore-pattern Check {
  filePath: '/Users/joseph/Sites/kohlmannj/typescript-eslint-dot-notation-index-access-optional-chaining-bug/src/index.ts',
  dot: false,
  relativePath: 'src/index.ts',
  result: false
} +1ms
  eslint:file-enumerator Yield: index.ts +418ms
  eslintrc:cascading-config-array-factory Load config files for /Users/joseph/Sites/kohlmannj/typescript-eslint-dot-notation-index-access-optional-chaining-bug/src. +2ms
  eslintrc:cascading-config-array-factory Cache hit: /Users/joseph/Sites/kohlmannj/typescript-eslint-dot-notation-index-access-optional-chaining-bug/src. +0ms
  eslint:cli-engine Lint /Users/joseph/Sites/kohlmannj/typescript-eslint-dot-notation-index-access-optional-chaining-bug/src/index.ts +0ms
  eslint:linter Linting code for /Users/joseph/Sites/kohlmannj/typescript-eslint-dot-notation-index-access-optional-chaining-bug/src/index.ts (pass 1) +0ms
  eslint:linter Verify +0ms
  eslint:linter With ConfigArray: /Users/joseph/Sites/kohlmannj/typescript-eslint-dot-notation-index-access-optional-chaining-bug/src/index.ts +0ms
  eslint:linter Generating fixed text for /Users/joseph/Sites/kohlmannj/typescript-eslint-dot-notation-index-access-optional-chaining-bug/src/index.ts (pass 1) +639ms
  eslint:source-code-fixer Applying fixes +0ms
  eslint:source-code-fixer shouldFix parameter was false, not attempting fixes +0ms
  eslint:file-enumerator Leave the directory: /Users/joseph/Sites/kohlmannj/typescript-eslint-dot-notation-index-access-optional-chaining-bug/src +639ms
  eslint:file-enumerator Complete iterating files: ["src"] +0ms
  eslint:cli-engine Linting complete in: 1058ms +639ms

/Users/joseph/Sites/kohlmannj/typescript-eslint-dot-notation-index-access-optional-chaining-bug/src/index.ts
  14:16  error  ["hello"] is better written in dot notation  @typescript-eslint/dot-notation

✖ 1 problem (1 error, 0 warnings)
  1 error and 0 warnings potentially fixable with the `--fix` option.

error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
➜  typescript-eslint-dot-notation-index-access-optional-chaining-bug git:(main) ✗

Versions

package version
@typescript-eslint/eslint-plugin 4.26.1
@typescript-eslint/parser 4.26.1
TypeScript 4.3.2
ESLint 7.28.0
node 14.5.0
@kohlmannj kohlmannj added package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin triage Waiting for maintainers to take a look labels Jun 9, 2021
@bradzacher bradzacher added bug Something isn't working and removed triage Waiting for maintainers to take a look labels Jun 10, 2021
@bradzacher
Copy link
Member

the problem here is that the type of dingus?.nested is reported by TS as Nested | undefined.
So TS returns nothing for this call:

const indexType = typeChecker.getIndexTypeOfType(
objectType,
ts.IndexKind.String,
);

@djcsdy
Copy link
Contributor

djcsdy commented Aug 5, 2021

I'm working on a fix for this.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants