Ответ 1
VSCode должен иметь эту функцию из коробки, только что протестированной в stackblitz: https://stackblitz.com/edit/angular-type-assertion?file=src/app/app.component.html
У меня есть шаблон, который выглядит следующим образом (я использую какой-то компонент, который использует это как основу для повторяющегося элемента, это p-pickList, но вопрос не является специфическим для этого компонента, как пример)
Для фона предположим, что у меня есть тип Foo
а мой компонент имеет foos: Foo[]
, я <p-pickList>
компоненту <p-pickList>
под атрибутом [source]
и выполняет его внутреннюю *ngFor
для него, все, что мне нужно сделать, это предоставить шаблон
<ng-template let-foo pTemplate="item">
...
{{ foo.anythingGoesHereWithNoWarningAndNoAutocomplete }}
Однако информация о типе на foo
кажется, потеряна.
Я большой поклонник безопасности типов, и мне нравится, что Intellij (или любой другой редактор) может показать мне предупреждение, если внутри шаблона я делаю что-то вроде указания недопустимого атрибута foo
Если бы у меня была обычная *ngFor
, она бы *ngFor
тип foo
<div *ngFor="let foo of foos">
{{ foo.autoCompleteWorksInMostIDEsAsWellAsWarningIfInvalidProp }}
Есть ли какой-либо синтаксис, который позволит мне намекнуть на тип let-foo
? (и, надеюсь, большинство IDE узнают).
Если я не хочу полагаться на IDE, есть ли способ проверить тип компилятора ng foo
(объявленный let-foo)?
tl; dr есть синтаксис, который позволяет мне вводить аннотацию входной переменной шаблона? например, что-то вроде синтаксиса?
let-foo="$implicit as Foo"
или let-foo-type="Foo"
?
Одна глупая идея состоит в том, чтобы иметь функцию идентификации в моем компоненте, например
identity(foo: Foo): Foo {
return foo;
}
но делать
{{ identity(foo).fooProp }}
Это не большое улучшение
{{ (foo as Foo).fooProp }}
VSCode должен иметь эту функцию из коробки, только что протестированной в stackblitz: https://stackblitz.com/edit/angular-type-assertion?file=src/app/app.component.html
Использование интерфейсов может привести к поведению, которое вы упомянули:
в ts файле, определите интерфейс:
export interface Dog {
name: string;
age: number;
}
в компоненте определите переменную:
@Component()...{
...
mrSnuggles: Dog = {
name: 'mrSnuggles',
age: 10
};
}
и в шаблоне:
{{mrSnuggles.food}}
вы можете увидеть ошибку (intellij idea):
Посмотрим, что такое угловое сходство и как оно работает!
<p *ngFor="let number of [{v: 101},{v: 102}, {v: 103}]">{{number.v}}</p>
Мы можем переписать его без *
магии
<ng-template ngFor let-number [ngForOf]="[{v: 101},{v: 102}, {v: 103}]">
<p>{{number.v}}</p>
</ng-template>
Без наблюдателей (ngDoCheck) он может быть таким же, как (но ngTemplateOutlet не имеет typecheck):
<ng-template let-number #templateRef>
<p>{{number.v}}</p>
</ng-template>
<ng-container *ngTemplateOutlet="templateRef; context: {$implicit: {v: 101}}"></ng-container>
<ng-container *ngTemplateOutlet="templateRef; context: {$implicit: {v: 102}}"></ng-container>
<ng-container *ngTemplateOutlet="templateRef; context: {$implicit: {v: 103}}"></ng-container>
Или мы можем создать его сами
// template
<button (click)=create(templateRef)>create</button>
// TS
constructor(private _viewContainerRef: ViewContainerRef) {
}
create(templateRef: TemplateRef<{$implicit: {v: number;}}>) {
this._viewContainerRef.createEmbeddedView(templateRef, {$implicit: {v: 101}});
this._viewContainerRef.createEmbeddedView(templateRef, {$implicit: {v: 102}});
this._viewContainerRef.createEmbeddedView(templateRef, {$implicit: {v: 103}});
}
TL; DR
Шаблон typecheck magic происходит внутри viewContainerRef.createEmbeddedView
. (например, ngFor); Но он предполагает, что принимает templateRef.
Угловой может компилироваться в AOT:
<p *ngFor="let num of [{v:1}, {v:2}]">
{{num.does.not.exist.completly}}
</p>
Так как я понял, мы должны предположить, какие типы шаблонов имеют, но проверить, когда экземпляр шаблона (путем createEmbeddedView
);
Проблема в том, что никакой информации о типе нет. <ng-template let-foo pTemplate="item">
- это просто объявление шаблона, оно еще не привязано ни к какому типу/контексту, просто к некоторому динамическому типу, который имеет или может иметь anythingGoesHereWithNoWarningAndNoAutocomplete
нибудьGoesHereWithNoWarningAndNoAutocomplete. Без надлежащей поддержки дженериков невозможно иметь такие типы безопасности.
Найдено эта проблема и предлагаемое решение разрешить ввод шаблона переменных публиковать информацию о типе, так что Иды могут обеспечить лучшее завершение на GitHub здесь. Эта функция в настоящее время находится в разработке, и, надеюсь, она будет выпущена в будущем выпуске Angular. Вы должны использовать расширение Angular Language Service в VS Code или Sublime Text. Вы можете быть уверены в поддержке расширения, потому что он работает над командой Angular. Для получения дополнительной информации ознакомьтесь с этим чтением и документами.
Как вы упомянули, это может быть достигнуто с помощью функции идентификации, но это вызовет серьезную проблему с производительностью, и это будет беспорядок, поддерживающий эту функциональность для разных типов.