Я пытаюсь реализовать шаблон стратегии с использованием обобщений в Typescript. Идея состоит в том, чтобы иметь один маппер с ключом всех возможных типов, тогда значение будет иметь все вопросы (которые будут отображаться с React), необходимые для этого конкретного типа (позже он будет расширен, чтобы также иметь валидации и другие вещи, связанные с этим тип).
Это объекты для применения шаблона к
export interface Book {
id: string;
type: string;
title: string;
author: string;
}
export interface Novel extends Book {
genre: string;
}
Это набор для вопросов
export interface BookQuestionProps<T> {
book: T;
}
//implementation
export const titleQuestion: React.FunctionComponent<BookQuestionProps<Book>> = ({
book
}: BookQuestionProps<Book>) => {
return <input type="text" value={book.title} />
}
export const genreQuestion: React.FunctionComponent<BookQuestionProps<Novel>> = ({
book
}: BookQuestionProps<Novel>) => {
return <input type="text" value={book.genre} />
}
Это основная часть шаблона
export interface BookMapperStrategy<T> {
questions: React.FunctionComponent<BookQuestionProps<Book>>[]
}
export interface BookTypeMapperStrategy<T> {
[type: string]: BookMapperStrategy<T>;
}
После всех этих настроек реализация будет выглядеть примерно так:
//specific strategy for novel
const novelQuestions: React.FunctionComponent<BookQuestionProps<Novel>>[] = [
titleQuestion,
genreQuestion
]
const novelMapperStrategy: BookMapperStrategy<Novel> = {
questions: novelQuestions
}
// setup strategy pattern mapper
const bookTypeMapperStrategy: BookTypeMapperStrategy<Book> = {
novel: novelMapperStrategy,
}
//print questions
const novel: Novel = {
id: '',
type: 'novel',
title: '',
author: '',
genre: ''
}
bookTypeMapperStrategy[novel.type].questions.map((question) => {
React.createElement(question, {
novel
})
})
Затем Typescript выдаст мне ошибку компиляции на novelQuestions
, особенно при установке titleQuestion
в массиве следующее:
Type 'FunctionComponent<BookQuestionProps<Book>>' is not assignable to type 'FunctionComponent<BookQuestionProps<Novel>>'.
The types of 'propTypes.book' are incompatible between these types.
Type 'Validator<Book>' is not assignable to type 'Validator<Novel>'.
Type 'Book' is not assignable to type 'Novel'.ts(2322)
Я попытался изменить интерфейс на объединение типов, но это дает еще больше ошибок.
Я бы подумал, что, поскольку Novel
является потомком Book
, передача titleQuestion
типа React.FunctionComponent<BookQuestionProps<Book>>
в состав React.FunctionComponent<BookQuestionProps<Novel>>
будет работать, потому что Book
является родителем из Novel
?