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

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

Фон

У меня есть шаблон, который выглядит следующим образом (я использую какой-то компонент, который использует это как основу для повторяющегося элемента, это 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 }}

Вопросы:

  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 }}

4b9b3361

Ответ 2

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

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

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

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

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

и в шаблоне:

  {{mrSnuggles.food}}

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

enter image description here

Ответ 3

Посмотрим, что такое угловое сходство и как оно работает!

<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);

Ответ 4

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

Ответ 5

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

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