用 typescript React钩子

ybzsozfc  于 2023-02-25  发布在  TypeScript
关注(0)|答案(2)|浏览(159)

我有一个钩子

import { userDB } from 'app/services/DBFunctions';
import { auth } from 'Fire';
import { collection, query, limit as fLimit, onSnapshot } from 'firebase/firestore';
import { IInvoice, IScheduledEmail, IScheduledInvoice, ITableData } from 'Interface';
import React, { useEffect, useState } from 'react';

interface Props {
    collectionPath: 'scheduled-invoices' | 'scheduled-emails'
}

const useScheduledFunctions = (props: Props) : IScheduledInvoice[] | IScheduledEmail[] => {
    const {collectionPath} = props
    const [scheduledFunctions, setScheduledFunctions] = useState<IScheduledInvoice[] | IScheduledEmail[]>([])
    const user = auth.currentUser

    useEffect(()=> {
        let queryCollection = query(
            collection(userDB(), collectionPath),
        )
        onSnapshot(queryCollection, (snap: any)=> {
            let scheduledFunctions = snap.docs.map((doc: any)=> doc.data())
            setScheduledFunctions(scheduledFunctions)
        })   
    }, [user, collectionPath])

    return scheduledFunctions
};

导出默认useScheduledFunctions;
但是当我在组件中调用它的时候,类型不是IScheduledInvoice就是IScheduledEmail,有没有办法根据集合路径来推断钩子的类型,目前我调用它的时候,为了避免这种冲突,我是这样做的:

const scheduledEmails = useScheduledFunctions({collectionPath: 'scheduled-emails'}) as IScheduledEmail[]

但是我不喜欢这样做,而且似乎不是一个好的解决方案,因为我正在重写类型。

gstyhher

gstyhher1#

给你Playground

interface Props {
  collectionPath: 'scheduled-invoices' | 'scheduled-emails'
}

interface IScheduledInvoice {}

interface IScheduledEmail {}

type Return<T> = T extends { collectionPath: 'scheduled-emails' } ? IScheduledEmail[] : IScheduledInvoice[];

const useScheduledFunctions = <T extends Props>(props: T): Return<T> => {
  return []
};

const a = useScheduledFunctions({ collectionPath: 'scheduled-emails' });
const b = useScheduledFunctions({ collectionPath: 'scheduled-invoices' });

这个解决方案的优点是你可以在interface Props中添加任何属性。使用重载你必须实现每个可能的参数。
局限性:如果collectionPath有两个以上的值,我会使用重载。

fykwrbwg

fykwrbwg2#

可以使用重载将某些参数类型与返回类型配对,然后提供接受和返回这两者的实现。

interface Props {
    collectionPath: 'scheduled-invoices' | 'scheduled-emails'
}

function useScheduledFunctions(props: { collectionPath: 'scheduled-invoices' }): IScheduledInvoice[]
function useScheduledFunctions(props: { collectionPath: 'scheduled-emails' }): IScheduledEmail[]
function useScheduledFunctions(props: Props): IScheduledInvoice[] | IScheduledEmail[] {
  return [] // implementation here
}

见Playground

相关问题