Vscode-ng-language-service: Type guards are not recognized in nested elements

Created on 4 Aug 2020  路  3Comments  路  Source: angular/vscode-ng-language-service

Describe the bug

When the component uses a function that returns a type predicate (type guard), the editor displays an error related to a missing field, even though the field is there and the code does compile (Angular v8.2).

To Reproduce
Use a type guard in *ngIf. Try using a field from the interface that's determined by it in nested elements.

// my-model.model.ts
type MyModel = (MyModelA | MyModelB) & { type: 'A' | 'B' };
interface MyModelA {  
  fieldA: any;
}
interface MyModelB {
  fieldB: any;
}
// foo.component.ts
public model: MyModel;
public isModelA(model): model is MyModelA {
  return model.type === 'A';
}

// foo.component.html


md5-1956e8def7f34e35cec69338ae3e15c2


Expected behavior

There is no error in the editor.

bug ivy

All 3 comments

similarly type guards aren't applying to contexts in language service (they do seem to apply while compiling just as this does)

export class NgLetContext<T = any> {
  // allows syntax "foo; let bar"
  $implicit: T = null!;
  // allows syntax "foo as bar"
  ngLet: T = null!;
}
@Directive({
  selector: '[ngLet]',
})
export class NgLetDirective<T> implements OnInit {
  @Input()
  set ngLet(value: T) {
    this.context.$implicit = this.context.ngLet = value;
  }

  constructor(private containerRef: ViewContainerRef, private templateRef: TemplateRef<NgLetContext>) {}
  private context = new NgLetContext<T>();

  static ngTemplateContextGuard<T>(dir: NgLetDirective<T>, ctx: unknown): ctx is NgLetContext<T> {
    return true;
  }

  ngOnInit() {
    this.containerRef.createEmbeddedView(this.templateRef, this.context);
  }
}
interface MyModel  { baz: ExampleValue }
// foo.component.ts
public model: MyModel;
<div *ngLet="model.baz as item">
   {{ item }}
</div>

In language service type (hover tooltip in vscode over item inside {{ }} at least) is any

When compiling, type is correctly ExampleValue

This is something that will be fixed in the upcoming Ivy-native language service (see https://github.com/angular/vscode-ng-language-service/issues/335#issuecomment-693545000), but not something we plan to fix before then due to the inherent limitations of the current language service implementation.

As Ayaz mentioned, this is resolved in the new Language Service which has been released in v11.1 as an opt-in. You can enable it in the extension settings:
image

Was this page helpful?
0 / 5 - 0 ratings