У меня есть компонент, который извлекает данные из серверной части, отображает их в таблице и позволяет пользователю сделать выбор.
Весь компонент основан на типе извлекаемых данных, поэтому он строго ограничен этим типом (Элемент).
Теперь мне нужен компонент для работы с немного другими типами данных на основе @Input.
Я не знаю, как заставить его работать с Typescript.
Упрощенный компонент выглядит так:
export class MyComponent implements OnInit {
@Input() public selectedItems: Item[] = [];
@Output() public validateButtonEmitter = new EventEmitter<Item[]>();
@Output() public cancelButtonEmitter = new EventEmitter<Item[]>();
constructor(private readonly facade: Facade) {}
public ngOnInit(): void {
this.facade.setInitialSelectedItems(this.selectedItems);
this.facade.getDataFromBackend();
}
public validateButtonHandler(selectedItems: Item[]): void {
this.validateButtonEmitter.emit(selectedItems);
}
public cancelButtonHandler(selectedItems: Item[]): void {
this.cancelButtonEmitter.emit(selectedItems);
}
}
Мой план состоит в том, чтобы добавить параметр @Input для передачи нужных данных для извлечения. затем я модифицирую метод getDataFromBackend(), чтобы он принимал аргумент, позволяя динамически выбирать маршрут на основе входных данных. Однако я не уверен, как провести рефакторинг всех методов внутри компонента, чтобы они были более общими в отношении типов данных.
Любые рекомендации будут очень признательны!
@user3791775 user3791775 Спасибо за подсказку. Однако правильно ли я понимаю, что защита типов требует от меня указания всех возможных типов в каждом методе?





компоненты могут быть универсальными. например, код в вопросе будет выглядеть так
// generic could be restrictive. for example TItem extends {selected: boolean}
// will make sure that items passed have a selected field
export class MyComponent<TItem> implements OnInit {
@Input() public selectedItems: TItem[] = [];
@Output() public validateButtonEmitter = new EventEmitter<TItem[]>();
@Output() public cancelButtonEmitter = new EventEmitter<TItem[]>();
constructor(private readonly facade: Facade<TItem>) {} // most probably you want your facade to be generic as well
public ngOnInit(): void {
this.facade.setInitialSelectedItems(this.selectedItems);
this.facade.getDataFromBackend();
}
public validateButtonHandler(selectedItems: TItem[]): void {
this.validateButtonEmitter.emit(selectedItems);
}
public cancelButtonHandler(selectedItems: TItem[]): void {
this.cancelButtonEmitter.emit(selectedItems);
}
Спасибо за Ваш ответ. Как именно должен работать этот <TItem>? Я не знаком с этим
если вы привязываетесь к массиву чисел компонента [seleccted] = "nums", то все остальное общее (в данном случае 2 выхода) будет иметь один и тот же тип TItem — они будут выдавать числа. это похоже на машинописную функцию с общими аргументами и типом возвращаемого значения
Значит, мне следует сделать настенную библиотеку универсальной, включая магазин? Этот компонент является небольшой частью библиотеки.
зависит от того, как спроектирован API библиотеки. если вы делаете http-запросы внутри библиотеки - тогда да
Вы можете использовать концепцию базового компонента и расширить ее с помощью любого типа ввода, который вы передаете в T.
export abstract class MyComponentBase<T> implements OnInit {
@Input() public selectedItems: T[] = [];
@Output() public validateButtonEmitter = new EventEmitter<T[]>();
@Output() public cancelButtonEmitter = new EventEmitter<T[]>();
constructor(private readonly facade: Facade) {}
public ngOnInit(): void {
this.facade.setInitialSelectedItems(this.selectedItems);
this.facade.getDataFromBackend();
}
public validateButtonHandler(selectedItems: T[]): void {
this.validateButtonEmitter.emit(selectedItems);
}
public cancelButtonHandler(selectedItems: T[]): void {
this.cancelButtonEmitter.emit(selectedItems);
}
// Расширяем компоненты разного типа, например
export class MyComponentChild1 extends MyComponentBase<string>{}
export class MyComponentChild2 extends MyComponentBase<Item>{}
export class MyComponentChild3 extends MyComponentBase<'any-custom-type'>{}
Для этого вам может потребоваться изменить класс фасада на универсальный или заставить метод setInitialSelectedItems принимать предварительно определенные типы, которые могут вам понадобиться.
public setInitialSelectedItems(data: string | Item | 'any-custom-type') { }
это все Item, но вы можете прочитать TypeGuards и сужение