バグの説明
コンポーネントが型述語 (タイプ ガード) を返す関数を使用する場合、フィールドが存在し、コードがコンパイルされても (Angular v8.2)、エディターは欠落しているフィールドに関連するエラーを表示します。
再現する
*ngIf
タイプ ガードを使用します。 ネストされた要素でそれによって決定されるインターフェースのフィールドを使用してみてください。
// 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
予想される行動
エディタにエラーはありません。
同様に、タイプ ガードは言語サービスのコンテキストに適用されていません (コンパイル時に適用されるように見えます)
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>
言語サービスのタイプ (少なくとも{{ }}
内のitem
上に vscode でツールチップをホバーする) はany
コンパイル時、タイプは正しくExampleValue
これは、今後の Ivy ネイティブ言語サービスで修正される予定です (https://github.com/angular/vscode-ng-language-service/issues/335#issuecomment-693545000 を参照)。現在の言語サービスの実装に固有の制限があるため、それまでに修正してください。
Ayaz が述べたように、これは v11.1 でオプトインとしてリリースされた新しい言語サービスで解決されています。 拡張機能の設定で有効にすることができます。