簡體   English   中英

TypeScript 泛型:React 中具有聯合類型的道具

[英]TypeScript generics: Props with union type in React

在下面的代碼中,我在行props.onChange(e.target.value as typeof props.value)上收到錯誤:“類型為 'string | string[]' 的參數不可分配給類型為 'string & string 的參數[]'。”

e.target.value的類型是unknown 如果onChange只是類型(value: string) => void ,那么我會像這樣轉換: props.onChange(e.target.value as string)並且這會起作用。 同樣對於string[]

可能有一種方法可以使用泛型來完成這項工作,對嗎? 我還沒有弄清楚如何。

(為了清楚起見,我包括了e的類型;沒有必要明確說明)。

import { MenuItem, Select } from '@material-ui/core';
import React, { ChangeEvent, FC } from 'react';

interface SingleProps {
  value: string;
  onChange: (value: string) => void;
  multiple: false;
}

interface MultiProps {
  value: string[];
  onChange: (value: string[]) => void;
  multiple: true;
}

const ReportDateSelect: FC<SingleProps | MultiProps> = props => (
  <Select
    value={props.value}
    onChange={(e: ChangeEvent<{ name?: string; value: unknown }>) =>
      props.onChange(e.target.value as typeof props.value)
    }
    multiple={props.multiple}
  >
    {[1, 2, 3].map((c, i) => (
      <MenuItem key={i} value={c}>
        {c}
      </MenuItem>
    ))}
  </Select>
);

export default ReportDateSelect;

問題之一是,當您運行props.onChange ,打字稿實際上並不知道它在運行哪一個。

根據您的設置方式,您可以通過將onChange函數更改為以下內容來修復打字稿錯誤:

    onChange={(e: ChangeEvent<{ name?: string; value: typeof props.value }>) =>{
      if(props.multiple){
        props.onChange(e.target.value as typeof props.value)
      }else{
        props.onChange(e.target.value as typeof props.value)
      }
    }}

打字稿游樂場

這是執行通用方法的一種方法。 為此,如果 Type 是一個數組,我不確定如何使 multiple prop 為 true,所以我只是使用Array#isArray在實際組件中實現了這一點

interface ReportDateSelectProps<Type = string | string[]> {
  value: Type;
  onChange: (value: Type) => void;
}

function ReportDateSelect<Type = string | string[]>(props: ReportDateSelectProps<Type>): React.ReactNode {
  return (
    <Select
      value={props.value}
      onChange={(e: ChangeEvent<{ name?: string; value: Type }>) =>
        props.onChange(e.target.value)
      }
      multiple={Array.isArray(props.value)}
    >
      {[1, 2, 3].map((c, i) => (
        <MenuItem key={i} value={c}>
          {c}
        </MenuItem>
      ))}
    </Select>
  );
}
export default ReportDateSelect;

打字稿游樂場

暫無
暫無

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

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