有没有办法在打字稿和角度中为"let variable"类型键入提示IDE?



具有类似标记

<mat-cell *matCellDef="let request">
<a [href]="request.url" target="_blank">{{request.requestId}}</a>
</mat-cell>

我可以以某种方式键入提示 IDE 该请求属于Request类型吗?我在这里使用IntelliJ。

请注意,我在这里使用的是角度材料表,因此在这里声明request组件不是一个选项,因为它纯粹是模板变量。它包含由组件本身在每次行迭代中内部提供的行数据。

请注意,这是 MatDataTable 组件中使用的完全有效的标记。

作为

tableDataSource: MatTableDataSource<ToDoInterface>;

不键入模型,

这:

<ng-container matColumnDef="toDo">
<th mat-header-cell *matHeaderCellDef mat-sort-header>ToDo</th>
<td mat-cell *matCellDef="let model">
<ng-container *ngIf="assertItemType(model) as toDoModel">
{{toDoModel.toDo}}
</ng-container>
</td>
</ng-container>

哪里:

assertItemType(item: ToDoInterface): ToDoInterface {
return item;
}

工程。

但不确定这是否是最好的方法

这可以通过将变量包装在另一个ng-template中来解决

当使用*ngFor*ngIf时,IDE 会注意到类型断言。这在某种程度上是另一种解决方法,但我比其他解决方案更喜欢,因为它只是在 HTML 中添加了 2 行代码,当然,如果您只使用变量 1 或 2 次,那么其他解决方案会更好。我的回答:

取而代之的是:

<ng-template *ngTemplateOutlet="foo; context: {$implicit: {fooProp: 'Hello!'}}"></p>
<ng-template #foo let-args>
This is untyped: {{ args.fooProp }}<br>
</ng-template>

这样做:

<ng-template *ngTemplateOutlet="foo; context: {$implicit: {fooProp: 'Hello!'}}"></p>
<ng-template #foo let-untypedArgs>
<ng-template [ngIf]="identity(untypedArgs)" let-args="ngIf">
This is typed: {{ args.fooProp }}<br>
</ng-template>
</ng-template>
identity(foo: Foo): Foo {
return foo;
}

有了这个,现在如果你在你的上下文中添加一个无效的属性,你会得到以下编译错误,这很好,这是一个堆栈闪电战演示,这个解决方案的缺点是内部<ng-template>由于[ngIf]而稍后渲染。

属性"newFooProp"在类型"Foo"上不存在。

这与我在另一个问题上给出的答案相同。

应该小心模板中的函数。这是我使用的自定义管道。它在我的IDE(PhpStorm)中不断重构

import {Pipe, PipeTransform} from '@angular/core';
@Pipe({
name: 'asType',
pure: true,
})
export class AsTypePipe implements PipeTransform
{
transform<T>(value: any, clss: new (...args: any[]) => T): T
{
return value as T;
}
}

在模板中,您可以使用:

<ng-template let-item="someAnyType">
<span>{{(item | asType :Customer).name}}</span>
</ng-template>

定义的位置:

import {Customer} from 'somewhere';
public Customer: typeof Customer = Customer; //Type variable to use in templates
public customer: Customer; //Case sensitivity allows creating similar variables if needed.

虽然这个问题有点旧,但我喜欢添加一个用于实现 IDE 类型提示的方法。

首先,我们可以添加一个额外的方法,例如,

asRequest(request: any): Request{
return workflow as Workflow;
}

因此,现在您可以使用该方法包装request

<mat-cell *matCellDef="let request">
<a [href]="asRequest(request).url" target="_blank">{{asRequest(request).requestId}}</a>
</mat-cell>

所以现在asRequest(request)了正义的request.(你可以认为这是一个用于铸造的功能。其实是这样!

我知道这种方式会进行一些额外的函数调用,但它会做你需要的。

如果你没有类并且想使用管道,你可以做这样的事情:

import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'asType',
})
export class AsTypePipe implements PipeTransform {
transform<T>(value: unknown, type: T): T {
return value as typeof type;
}
}

使用组件中的数据:

@Input() nodes: IModelNode[] = [];

并将其用作

[attr.width]="(node | asType : nodes[0]).dimension?.width"

现在我终于明白了这个问题(在 OP 编辑之后)。

声明*matCellDef="let request"时,不能在模板中指定类型,但是,该局部变量应该已经在组件中键入。

使用 AM 表时,我们会有这样的东西,对吧?

<mat-table [dataSource]="dataSource">
<ng-container matColumnDef="name">
<mat-header-cell *matHeaderCellDef> Name </mat-header-cell>
<mat-cell *matCellDef="let user"> {{user.name}} </mat-cell>
</ng-container>
</mat-table>

我们不能键入user局部变量,但我们可以键入dataSource

所以,想象一下我们有这个接口:

export interface User {
name: string;
email: string;
}

而且我们的dataSource是用户的集合。然后我们将像这样键入它:

dataSource: User[] = this.getUsers();

现在我们告诉编译器,dataSource的每个元素都是类型User

相关内容

最新更新