Есть ли способ добавить утверждение типа / аннотацию к входной переменной шаблона? - PullRequest
0 голосов
/ 30 августа 2018

Фон

У меня есть шаблон, который выглядит следующим образом (я использую некоторый компонент, который использует его в качестве основы для повторяющегося элемента, это p-pickList, но вопрос не является специфическим для этого компонента, просто в качестве примера)

Для фона, скажем, у меня есть тип Foo, а у моего компонента foos: Foo[], я передаю его компоненту <p-pickList> под атрибутом [source], и он выполняет внутренний *ngFor для все, что мне нужно сделать, это предоставить шаблон

 <ng-template let-foo pTemplate="item">
   ...
   {{ foo.anythingGoesHereWithNoWarningAndNoAutocomplete }}

Однако информация о типе foo, похоже, утеряна.

Я большой поклонник безопасности типов, и мне нравится, что Intellij (или любой другой редактор) может показать мне предупреждение, если внутри шаблона я делаю что-то вроде указания недопустимого атрибута foo

Если бы у меня был обычный *ngFor, это вывело бы тип foo

<div *ngFor="let foo of foos">
  {{ foo.autoCompleteWorksInMostIDEsAsWellAsWarningIfInvalidProp }}

Вопросы:

  1. Существует ли какой-либо синтаксис, который позволит мне подсказывать тип let-foo? (и, надеюсь, большинство IDE узнают).

  2. Если я не хочу полагаться на 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 }}

Ответы [ 5 ]

0 голосов
/ 13 сентября 2018

Нашел эту проблему и предложил решение, позволяющее входным переменным шаблона публиковать информацию о типах, чтобы IDE могли обеспечить лучшее завершение на github здесь . Эта функция в настоящее время находится в стадии разработки, и, надеюсь, она появится в будущем выпуске Angular. Вам следует использовать расширение Angular Language Service в VS Code или Sublime Text. Вы можете быть уверены в поддержке расширения, потому что над ним работает команда Angular. Для получения дополнительной информации, закажите эти readme и документы .

Как вы упомянули, это может быть достигнуто с помощью функции идентификации, но это приведет к серьезным проблемам с производительностью, и это будет беспорядок, поддерживающий эту функцию для различных типов.

0 голосов
/ 11 сентября 2018

Проблема в том, что нет никакой информации о типе. <ng-template let-foo pTemplate="item"> - это просто объявление шаблона, оно еще не связано ни с каким типом / контекстом, просто с некоторым динамическим типом, который имеет или может иметь поле anythingGoesHereWithNoWarningAndNoAutocomplete. Без надлежащей поддержки непатентованных средств такой тип безопасности невозможен.

0 голосов
/ 10 сентября 2018

Использование интерфейсов может привести к описанному вами поведению:

в файле ts, определить интерфейс:

export interface Dog {
  name: string;
  age: number;
}

в компоненте определяют переменную:

@Component()...{
...
  mrSnuggles: Dog = {
    name: 'mrSnuggles',
    age: 10
  };
}

и в шаблоне:

  {{mrSnuggles.food}}

вы можете увидеть ошибку (intellij idea):

enter image description here

0 голосов
/ 11 сентября 2018

Давайте посмотрим, что такое angular, и как оно работает!

<p *ngFor="let number of [{v: 101},{v: 102}, {v: 103}]">{{number.v}}</p>

Мы можем переписать его без * magic

<ng-template ngFor let-number [ngForOf]="[{v: 101},{v: 102}, {v: 103}]">
  <p>{{number.v}}</p>
</ng-template>

Без наблюдателей (ngDoCheck) оно может быть таким же, как (но у ngTemplateOutlet нет проверки типов ):

<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

Шаблон проверки типа магии происходит внутри viewContainerRef.createEmbeddedView. (например ngFor ); Но это предполагает, что принимает templateRef.

Angular может компилироваться в AOT:

<p *ngFor="let num of [{v:1}, {v:2}]">
  {{num.does.not.exist.completly}}
</p>

Итак, как я понял, мы должны предполагать, какие шаблоны имеют шаблоны, но проверять, когда шаблон создается (createEmbeddedView);

0 голосов
/ 07 сентября 2018

VSCode должен иметь эту функцию из коробки, только что протестирован в stackblitz: https://stackblitz.com/edit/angular-type-assertion?file=src/app/app.component.html

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...