React TS. Объединить 2 и более компоненты выполняющую одну и ту же задачу (но типы даных и параметры разные) в одну универсальную

React TS.
Объединить 2 и более компоненты выполняющую одну и ту же задачу (но типы даных и параметры разные) в одну универсальную.

Подброно: Нужно декомпозировать компоненты в 1. Но проблема в том, что list из store имеет разные данные, функции (там есть и общие но у них тоже разные типы и параметры ) и тип данных в 1-ой это quiz.list с IQuizRow[] , а во 2-ой это quiz_session.list с типом IQuizSessionRow[].

Но по сути эти компоненты выполняют один алгоритм. Отображают список.

Пробовал в props прокидывать list: any[] и store: any. Но тогда это немного не правильно с точки зрения TS. нужно чтобы точно знал что есть в props.

Также не подходит вариант с общим типом который будет равен типам props. так так придется каждый раз добавлять туда новый тип если нужен новый список с другими данными, и если там будет 2+ типов это по сути тот же any так что опять нарушаем принцип TS.

  1. Это список викторин
const QiuzList = observer(() => {
    const {store} = useContext(Context);
    const navigate = useNavigate();
    const {t} = useTranslation();
    const {height} = useWindowSize()

    useEffect(() => {
        store.quiz.list.loader.set(true)
        return () => store.quiz.list.loader.set(true)
    }, [])

    const [limit, setLimit] = useState<number>(5);
    const [offset, setOffset] = useState<number>(0);

    const [list, setList] = useState<IQuizRow[]>([]);

    useEffect(() => {
        reload()
    }, [offset])

    const reload = () => {
        store.quiz.list.request({limit, offset}).then(r => {
            console.log(r)
            setList([...list, ...store.quiz.list.get().results])
        })
    }

    return <div>...</div>
});
  1. Это список сессий


const QiuzSessionList = observer(() => {
    const {store} = useContext(Context);
    const navigate = useNavigate();
    const {t} = useTranslation();
    const {height} = useWindowSize()

    useEffect(() => {
        store.quiz_session.list.loader.set(true)
        return () => store.quiz_session.list.loader.set(true)
    }, [])

    const [limit, setLimit] = useState<number>(5);
    const [offset, setOffset] = useState<number>(0);

    const [list, setList] = useState<IQuizSessionRow[]>([]);

    useEffect(() => {
        reload()
    }, [offset])

    const reload = () => {
        store.quiz_session.list.request({limit, offset}).then(r => {
            console.log(r)
            setList([...list, ...store.quiz_session.list.get().results])
        })
    }

    return <div>...</div>

})

Какая же мне нужна компонента примерно. Дальше псевдокод:

type Props = {
    props_list: ТИП КОТОРЫЙ РАВЕН YOUR_LIST_STORE из store со всеми достпуными в ней функциями,
    row: YOUR_LIST_ROW_TYPE,
}

const List = observer(({props_list, row}:Props) => {
    const {store} = useContext(Context);

    useEffect(() => {
        // вот тут я вроде вызываю функции,
        // но я точно не могу быть уверен,
        // что такая функия есть. так как type any
        props_list.loader.set(true)
        return () => props_list.loader.set(true)
    }, [])

    const [limit, setLimit] = useState<number>(5);
    const [offset, setOffset] = useState<number>(0);

    const [virtual_list, setVirtualList] = useState<YOUR_LIST_ROW_TYPE[]>([]);

    useEffect(() => {
        reload()
    }, [offset])

    const reload = () => {
        // вот тут я вроде вызываю функции, 
        // но я точно не могу быть уверен,
        // что такая функия есть. так как type any
        props_list.request({limit, offset}).then(r => {
            console.log(r)
            setVirtualList([...virtual_list, ...props_list.get().results])
        })
    }

    return <div>...</div>

})

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

type Props = {
    props_list: any,
    row: any,
}

const List = observer(({props_list, row}:Props) => {

    useEffect(() => {
        props_list.loader.set(true)
        return () => props_list.loader.set(true)
    }, [])

    const [limit, setLimit] = useState<number>(5);
    const [offset, setOffset] = useState<number>(0);

    const [virtual_list, setVirtualList] = useState<typeof row[]>([]);

    useEffect(() => {
        reload()
    }, [offset])

    const reload = () => {
        props_list.request({limit, offset}).then((r: any) => {
            console.log(r)
            setVirtualList([...virtual_list, ...props_list.get().results])
        })
    }

    return <div>...</div>

})

Ответы (1 шт):

Автор решения: Sire IMPACTUS
type PartOne = {
    type: '1',
    list: string
}
type PartTwo = {
    type: '2',
    list: Array<string>
}
type MultipleTypes = PartOne | PartTwo
const ComponentMultipleTypes = (props: MultipleTypes) => {
    return null;
}

<ComponentMultipleTypes type="1" list={["1231231"]} /> - error
<ComponentMultipleTypes type="1" list={"1231231"} /> - ok

<ComponentMultipleTypes type="2" list={["1231231"]} /> - ok
<ComponentMultipleTypes type="2" list={"1231231"} /> - error
→ Ссылка