簡體   English   中英

自定義反應掛鈎的窄聯合類型

[英]Narrow union types for custom react hook

我有 4 個對象,它們幾乎沒有相似的鍵和一些不同的鍵。 我正在使用他們的聯合進行數據庫操作,就像這樣->

type Objects = Food | Diary | Plan | Recipe;

分頁自定義鈎子

function usePaginate (key: string, options: Options) {
    const [data,setData] = useState<Objects[]>([]);
    const perPage = 10;
    const [first, setFirst] = useState(0);
    const [last, setLast] = useState(perPage);

    const links = () => data.slice(first,last);

    function paginate(clicked: 'next' | 'previous') {
        if(clicked === 'next' && data.length > (first+perPage)) {
            setFirst(first+perPage);
            setLast(last+perPage);
        }
        if(clicked === 'previous' && (first-perPage) >= 0) {
            setFirst(first-perPage);
            setLast(last-perPage);
        }
    }

    useEffect(()=>{
        setData(getData(key,options));
    },[])

    return [links(),paginate] as const;
}

在 StockDisplay 組件中調用自定義掛鈎

const StockDisplay = () => {
    const [foods, paginate] = usePaginate('foods',{'sort':['-stocked','info.name']});
    return (<>{foods.map(food => <Stock data={food} key={food.id} />)}</>)
    // I have also tried adding a check like below but the error persists. 'stocked' is a key that only exists in Food type
    return (<>{('stocked' in foods) && foods.map(food => <Stock data={food} key={food.id} />)}</>)
}

此時,foods 的類型是const foods: Objects[] & paginate 的類型是const paginate: (clicked: "next" | "previous") => void 但是返回行拋出這個錯誤->

Type 'Objects' is not assignable to type 'Food'.ts(2322)
Stock.tsx(12, 26): The expected type comes from property 'data' which is declared here on type 'IntrinsicAttributes & { data: Food; }'

這是因為在下面的 Stock 組件中,數據被定義為Food類型,但在上面的 StockDisplay 組件中,我接收到Objects[]

庫存成分

const Stock = ({data} : {data: Food}) => {
     return (
          <></>
     )
}

我的問題是,如何將Objects[] output 從鈎子縮小到 StockDisplay 組件中的Food[]

1. 使用類型轉換的快速解決方法

const StockDisplay = () => {
    const [foods, paginate] = usePaginate('foods',{'sort':['-stocked','info.name']});
    return (<>{(foods as Food[]).map(food => <Stock data={food} key={food.id} />)}</>)
    // I have also tried adding a check like below but the error persists. 'stocked' is a key that only exists in Food type
    return (<>{('stocked' in foods) && foods.map(food => <Stock data={food} key={food.id} />)}</>)
}

2.使用generics

function usePaginate<T>(key: string, options: Options): readonly [T[], (clicked: 'next' | 'previous') => void] {
    const [data,setData] = useState<Objects[]>([]);
    const perPage = 10;
    const [first, setFirst] = useState(0);
    const [last, setLast] = useState(perPage);

    const links = () => data.slice(first,last);

    function paginate(clicked: 'next' | 'previous') {
        if(clicked === 'next' && data.length > (first+perPage)) {
            setFirst(first+perPage);
            setLast(last+perPage);
        }
        if(clicked === 'previous' && (first-perPage) >= 0) {
            setFirst(first-perPage);
            setLast(last-perPage);
        }
    }

    useEffect(()=>{
        setData(getData(key,options));
    },[])

    return [links(),paginate] as const;
}
const StockDisplay = () => {
    const [foods, paginate] = usePaginate<Food>('foods',{'sort':['-stocked','info.name']});
    return (<>{foods.map(food => <Stock data={food} key={food.id} />)}</>)
    // I have also tried adding a check like below but the error persists. 'stocked' is a key that only exists in Food type
    return (<>{('stocked' in foods) && foods.map(food => <Stock data={food} key={food.id} />)}</>)
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM