Проверка типов в Angular 2 шаблонах
Мы создаем приложение в Angular 2 и TypeScript. Мы стараемся статически проверять типы, где это возможно. Есть ли способ проверить типы в шаблонах? Рассмотрим следующий фрагмент:
<foo [data]="dataObj"></foo>
Предположим, что data
в Foo
имеет некоторый тип TData
. Однако по умолчанию ничто не мешает мне передать dataObj
, который не соответствует TData
. Существует ли расширение typescript для шаблонов Angular, которые будут проверять типы в таком случае?
Ответы
Ответ 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);
}