Подтвердить что ты не робот

Проверка типов в Angular 2 шаблонах

Мы создаем приложение в Angular 2 и TypeScript. Мы стараемся статически проверять типы, где это возможно. Есть ли способ проверить типы в шаблонах? Рассмотрим следующий фрагмент:

<foo [data]="dataObj"></foo>

Предположим, что data в Foo имеет некоторый тип TData. Однако по умолчанию ничто не мешает мне передать dataObj, который не соответствует TData. Существует ли расширение typescript для шаблонов Angular, которые будут проверять типы в таком случае?

4b9b3361

Ответ 1

Я думаю, что IDE или linter могут поймать это для вас, но если кому-то это действительно нужно, одним из вариантов было бы создание Pipe для проверки типа во время выполнения.

@Pipe({ name: 'typeCheck' })
export class TypeCheckPipe implements PipeTransform {

  transform(value: any, classType: object): any[] {
    if (value &&
      !(value instanceof classType)
    ) {
        throw new TypeError("Input is not instanceof " + classType + 
                            " but was " + typeof(value));
    }
    return value;
  }
}

Вы можете использовать его в шаблоне компонента следующим образом:

<custom-component [coolInput]="coolInput | typeCheck:coolInputClass"></custom-component>

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

@Component({
  selector: 'my-app',
  template: `
  <div>
    <custom-component [coolInput]="coolInput | typeCheck:coolInputClass"></custom-component>
  </div>
  `,
})
export class App {
  coolInput: CoolInput;
  coolInputClass: object = CoolInput;

  constructor() {
    this.coolInput = "This is the wrong type";
  }
}

Вот Plunker, иллюстрирующий сообщение об ошибке работы (выбрано через Zone). https://plnkr.co/edit/WhoKSdoKUFvNbU3zWJy6?p=preview

Ответ 2

Если вы используете визуальный код студии, вы можете попробовать расширение language service. Он все еще находится в тяжелом развитии, и вы можете рассмотреть его в бета-версии. Но когда я определенно скажу, что это сделало меня более продуктивным. Не только его проверка типа, но и cmd + щелчок компонентов, чтобы перейти к их источнику.

Если я не ошибаюсь, этот проект в конечном итоге будет объединен с vscode it self, когда он будет несколько стабильным, поскольку его в vscode наилучшим образом интересует Храните angular разработчиков продуктивно.

Вы можете быть уверены в поддержке расширения, потому что он работает командой angular. Для получения дополнительной информации ознакомьтесь с этим readme

Изменить: возвышенный текст и поддержка webstorm тоже.

Ответ 3

Ваши компоненты Input() должны иметь тип. Скажем, у вас есть компонент списка

import {Component, Input, OnInit } from '@angular/core';

import { Items } from '../../../services/Items';

@Component({
  selector: 'my-list',
  templateUrl: './my-list.component.html',
  styleUrls: ['./my-list.component.scss'],
})
export class CategoryListComponent implements OnInit {
  @Input() items: Items;

  constructor() { }

  ngOnInit() { }
}

"Элементы" должны быть определены как интерфейс и импортированы

export interface List {
  name: string,
  children: Items[]
}

export interface Item {
  name: string;
  slug: string;
  imageUrl: string;
  children: Item[];
}

теперь вы можете использовать его как это

<my-list [items]="items"></my-list>

Ответ 4

Вы можете использовать трубку:

export class ObjectTypePipe implements PipeTransform {

    transform(value: any, args?: any): string {

        if (value != undefined && value != null) {
            return value.constructor.name.toString();
        }
        return "";
    }
}

Ответ 5

WebStorm от Jetbrains может это сделать.

Мой оригинальный ответ:

Я не думаю, что существует надежный способ сделать это, не делая подумайте, как React делает с расширением JSX или TSX для языка.

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

Ответ 6

Здесь приведена документация о том, как проверять типы с помощью TypeScript (прокрутите вниз до раздела "Тип и типы дифференциации" ), также здесь - подробный ответ с плункером, показывающим, как использовать параметры проверки типа.

Мне кажется, что я нарушаю протокол, чтобы не отвечать на этот вопрос внутри, поэтому, чтобы быть кратким, вы, скорее всего, захотите использовать "Защищенные пользователем типы гвардейцев" и "Защиты типа instanceof", Обратите внимание, что "защита типа instanceof" работает только в том случае, если у объекта Object есть конструктор. Вот ссылка на plunker из моего другого ответа. Раздел, выполняющий всю работу, находится на странице "app/child.component.ts".

ngOnChanges(changes: {[propertyName: string]: SimpleChange}) {
  console.log();
  console.log("Custom function isSimpleChange:", this.isSimpleChange(changes));
  console.log("Using instanceof SimpleChange:", (changes instanceof SimpleChange));
  console.log("Using Object.prototype.toString.call():", Object.prototype.toString.call(changes));
  console.log("Logging the object itself:",changes);
  console.log("-----------------------------------------------------------------------------------------");
  let testExample = new ExampleObject();
  console.log("Custom function isExampleObject:", this.isExampleObject(testExample));
  console.log("Using instanceof ExampleObject:", (testExample instanceof ExampleObject));
  console.log("Using Object.prototype.toString.call():" + Object.prototype.toString.call(testExample));
  console.log(testExample);
}