Skip to content

[no-unsafe-member-access] Extending namespaces trigger error #2740

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

Closed
3 tasks done
susnux opened this issue Nov 5, 2020 · 1 comment · Fixed by #2753
Closed
3 tasks done

[no-unsafe-member-access] Extending namespaces trigger error #2740

susnux opened this issue Nov 5, 2020 · 1 comment · Fixed by #2753
Labels
bug Something isn't working good first issue Good for newcomers package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin

Comments

@susnux
Copy link

susnux commented Nov 5, 2020

  • 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

declare namespace FG {
	interface A {}
}

interface B extends FG.A {
}

You can also look at this example repo: https://github.com/susnux/typescript-eslint-no-unsafe-member-access

Expected Result
No error message

Actual Result

typescript-eslint-no-unsafe-member-access/src/test.d.ts
6:21 error Unsafe member access .A on an any value @typescript-eslint/no-unsafe-member-access

Additional Info
Nothing special, you can simply reproduce this.
I experienced the same issue (this) as reported by @tao-cumplido in #1868.

Versions

package version
@typescript-eslint/eslint-plugin 2.27.0
@typescript-eslint/parser `2.27.0
@typescript-eslint/typescript-estree 2.27.0
@typescript-eslint/experimental-utils 2.27.0
TypeScript 4.0.5
node 12.18.4
npm 6.14.6
@bradzacher bradzacher added bug Something isn't working good first issue Good for newcomers package: eslint-plugin Issues related to @typescript-eslint/eslint-plugin labels Nov 6, 2020
@bradzacher
Copy link
Member

The root of this problem is that for TSInterfaceHeritage we emit a MemberExpression for the heritage.

class B extends FG.A {} // FG.A is a MemberExpression ✅
type B = FG.A; // FG.A is a TSQualifiedName ✅

class B implements FG.A {} // FG.A is a MemberExpression ❌
interface B extends FG.A {} // FG.A is a MemberExpression ❌

https://astexplorer.net/#/gist/4d80b0e52f9c5a85c3e8e5965159c0b0/f19196f6c60b81e792172e7c0adcfc8f676270d0

However - this is a type-only location, so ideally it should be a TSQualifiedName.

Why do we emit a MemberExpression?

Because TS emits a PropertyAccessExpression here - and our parser (mostly) just converts TS's AST as written.

Why does TS emit this?

Because the TS parser shares the logic for parsing this between:

  • class extends
  • interface extends
  • class implements

TS has a semantic error to prevent you from doing anything too stupid - however it does allow some stupid code: microsoft/TypeScript#41420

What's the fix?

Pretty straight-forward - the selectors need to be updated to ignore any MemberExpression whose parent is either TSInterfaceHeritage or TSClassImplements.

MemberExpression: checkMemberExpression,
'MemberExpression[computed = true] > *.property'(

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