codelyzer: no-access-missing-member and extended classes

Hi Minko,

I don’t know if the following problem is related to #190, but if I set the property on the subject to true (as recommended) when I have an extended class I get warnings. For example:

@Component({
    templateUrl: 'signin.component.html'
})

export class SigninComponent extends Signin {
    constructor(public router: Router, public authenticationService: AuthenticationService) {
        super(router, authenticationService);
    ...
    }
}
export class Signin {

    model: any = {};

    errorMessage: string = "";

    constructor(public router: Router, public authenticationService: AuthenticationService) { }
    ...
}

I get the following warnings:

app/account/signin.component.html[11, 59]: The property "model" that you're trying to access does not exist in the class declaration.
app/account/signin.component.html[10, 71]: The property "errorMessage" that you're trying to access does not exist in the class declaration.

Packages: “codelyzer”: “2.0.0-beta.3”, “tslint”: “4.0.2”, “typescript”: “2.0.10”

Note that up to codelyzer 2.0.0-beta.1 I didn’t get any error.

Thanks,

Roberto

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Reactions: 44
  • Comments: 75 (17 by maintainers)

Commits related to this issue

Most upvoted comments

Ok, later this week I’ll align to the changes introduced by 4.0.2 and push it.

I’ll work on this during the weekend. Hopefully, by Monday we’ll have these working:

Imported base class

// base.ts
class Base {
  bar;
}
// child.ts
import { Base } from './base';

@Component({
  selector: 'child',
  template: '{{ bar }}'
})
class Child extends Base {}

Base class declared in the same file

class Base {
  bar;
}

@Component({
  selector: 'child',
  template: '{{ bar }}'
})
class Child extends Base {}

BTW it also throws when referencing local template variable and reading different value (for ex. directive):

<input ngbDatepicker #d="ngbDatepicker">
<button (click)="d.toggle()">Toggle date picker</button>

Results in error:

ERROR: src/em/components/calendar/calendar.component.html[10, 61]:
The method "d" that you're trying to access does not exist in the class declaration.

Alright, it’s out in codelyzer@3.0.0-beta.0. I’ll work on beta.1 in the next few days, to make the metadata collection smarter.

@mgechev @wlngwang as a workaround while this issue is resolved, you can use this[‘your_prop_name’] in your template. Not ideal, but it gets the warning out of the way for now.

class Base {
  bar;
}

@Component({
  selector: 'child',
  template: '{{ this["bar"] }}'
})
class Child extends Base {}

Excuse me for the delay. There were a lot of things on my plate. I’ll try to come up with a fix in the next a couple of days/week.

I have to move the 3 release (i.e. the support for inheritance) as codelyzer 4, because in the meantime, while making 3 stable, tslint broke their backwards compatibility and I had to release support for tslint 5 as codelyzer 3.

What I can do is to release the support for inheritance as codelyzer 4.0.0-beta.0, if it’s more convenient for you.

upgrading from 3.0.0-beta.4 to 3.0.0 we seem to be getting this issue again. Is it the same or it just looks very similar?

CLI

There won’t be support for inheritance and it’s very likely the no-access-missing-member rule to be removed in version 4. The language service already handles this.

https://github.com/mgechev/codelyzer/issues/191#issuecomment-307685909

You can disable the rule and rely on the AoT build.

@mgechev sorry If I misunderstood, but I’m still having issues with extended classes.

It seems working fine for Classes, but not for templates inline and external .html with these versions:

@angular/*: 4.3.4
@angular/cli: 4.3.4
@angular/language-service: 4.3.4
codelyzer: 3.1.2
tslint-language-service@0.9.6

I can use the property in the extended class, however, if I try to access in the template, the command:

ng lint --type-check

Returns the error:

The property "config" that you're trying to access does not exist in the class declaration.

Eq:

export abstract class MyParentClass {
    public config: string = 'name';
}
@Component({
    selector: 'my-child-component',
    template: `<h1>{{config}}</h1>` // The property "config" that you're trying to access does not exist in the class declaration.
})
export class MyChildComponent extends MyParentClass {
     method() {
          this.config = 'new name'; // no complains
    }
}

I wonder how would I run ng-lint with AOT?

Thanks

@mgechev Can we support you with implementation? The branch 4.0.0-beta.4 seems to be not up to date, right?

Good news! Just pushed code which introduces support for extended classes. You can find it here.

I will release 2.0.1 once I make sure everything works properly.

What is the tslint property to disable this check for time being?

no-access-missing-member?

@asadsahi You have to disable the rule/tslint in the component (typescript file), not the template.

This problem is back in 3.x.x (3.0.0 and 3.0.1). I had to revert back to 3.0.0-beta.0 to get it to work.

I found that adding an interface to the base class that declares the shared properties also squashes this warning.

interface IControl {
      name: string;
}

@Component({
    selector: 'control'
})
class Control implements IControl {
    @Input()
    public name: string;
}

@Component({
   selector: 'button',
   template: '<span>{{name}}</span>'
class Button extends Control {
}

I’m not sure why, but seems to fix other auto-complete issues in IDEs as well.

To be clear, the issue was resolved for me when I updated to 3.0.0-beta.x the betas were fine, the final release now is bringing it back to me

with the next version of typescript 2.3 I think we can use https://github.com/angelozerr/tslint-language-service to solve that issue

I’ve been working on ngast for better metadata extraction.

Tomorrow I’ll reuse the TypeChecker with program aware walkers, to find the base classes and all symbols. Setting it as a todo item in Things! 👨‍💻

Related to https://github.com/mgechev/codelyzer/issues/64.

@mgechev I’m having this issue now. Any progress on this?

Try on src/app/example/example.component.ts

@pgrm there are a few codelyzer rules which provide static analysis for errors that have very tight intersection with ones that are supposed to be caught compile-time by the Angular compiler, and reported by the language service.

codelyzer aims to provide linting for style errors which can be found by providing a “shallow analysis” (one with no-type checking), only on top of the current file + external template/style.

There won’t be support for inheritance and it’s very likely the no-access-missing-member rule to be removed in version 4. The language service already handles this.

What @thinkingmedia mentioned doesn’t seem to work when you import the base class. Not even when you create an interface that extends the original one in another file.

I did run into the same issue and would like to try the 4.0.0-beta.

Is there no release yet?

@mgechev It seems this problem persist in newer versions as well. I still run into this problem with angular cli 1.0, codelyzer 2.1.1 and ts-lint 4.5.1 (unfortunately, I can’t upgrade ts-lint to the newst 5.xx version because of https://github.com/angular/angular-cli/issues/5848).

@mgechev sooner the better so our lint can pass on CI with that rule
So CLI I guess 😄

@guojenman your workaround worked for me. Was not just a property but a method.

class Base {
  bar(arg){return 'x'};
}

@Component({
  selector: 'child',
  template: '{{ this["bar"](arg) }}'
})
class Child extends Base {}

I’m doing this (redeclaring the var) but it’s quite annoying 😦

Yes, I said “didn’t”, this is the reason the issue is still open 😃