在typescript中扩展react-select接口属性

问题描述 投票:0回答:4

我为我的react-project定制了一个react-select下拉组件。当我尝试使用React.HTMLAttributes扩展界面时。它显示“没有与此调用匹配的重载”。 我尝试扩展不同的属性来获取默认值,如 id、标签、名称、占位符等。 如何获取 props 中的默认属性? 有没有人遇到过类似的问题?

示例代码:

import * as React from "react";

import ReactSelect from 'react-select';

export interface SelectProps extends React.HTMLAttributes<HTMLSelectElement | HTMLInputElement> {
    options: Array<any>;
    isMulti: boolean;
    isDisabled: boolean;

};

const Select: React.FC<SelectProps> = (props: SelectProps) => {

    return (<div>
        <label htmlFor={props.id}>{props.label}</label>
        <div>
            <ReactSelect
                {...props}
            />
        </div>
    </div>)
}
export default Select;

使用上面的代码后,我无法获取props.id或props.name等

javascript reactjs typescript react-select
4个回答
8
投票

编辑:

React-Select v5 现在原生支持 TypeScript,因此进行了一些类型更改(详细信息)。

这是 v5 (react-select/async) 的更新示例,类似于 v4 的原始示例:

import ReactSelectAsync, { AsyncProps } from "react-select/async";
import { GroupBase } from "react-select";

interface CustomSelectAsyncProps {
  additionalCustomProp: number;
}

function SelectAsync<
  OptionType,
  IsMulti extends boolean = false,
  GroupType extends GroupBase<OptionType> = GroupBase<OptionType>
>({
  additionalCustomProp,
  ...props
}: AsyncProps<OptionType, IsMulti, GroupType> & CustomSelectAsyncProps) {
  return <ReactSelectAsync {...props} />;
}

export default SelectAsync;

代码沙盒

原答案:

这记录在官方 react-select 文档中。

引用:

包装 Select 组件 通常,Select 组件被包装在整个应用程序中使用的另一个组件中,并且包装器应该与原始 Select 组件一样灵活(即,允许不同的选项类型、组、单选或多选)。为了提供这种灵活性,包装组件应该重新声明泛型并将它们转发到底层的 Select。以下是如何执行此操作的示例:

function CustomSelect<
  Option,
  IsMulti extends boolean = false,
  Group extends GroupBase<Option> = GroupBase<Option>
>(props: Props<Option, IsMulti, Group>) {
  return (
    <Select {...props} theme={(theme) => ({ ...theme, borderRadius: 0 })} />
  );
}

它还解释了如何使用额外的自定义道具来扩展道具:

您可以使用模块增强将自定义道具添加到选择道具类型中:

declare module 'react-select/dist/declarations/src/Select' {
  export interface Props<
    Option,
    IsMulti extends boolean,
    Group extends GroupBase<Option>
  > {
    myCustomProp: string;
  }
}

但我个人更喜欢仅使用带有自定义界面的

&
字符来添加自定义界面来添加自定义道具(使用
ReactSelectAsync
的示例,请参阅
... & CustomSelectAsyncProps
):

interface CustomSelectAsyncProps {
  additionalCustomProp: number;
}

function SelectAsync<
  OptionType extends OptionTypeBase,
  IsMulti extends boolean = false,
  GroupType extends GroupTypeBase<OptionType> = GroupTypeBase<OptionType>
>({
  additionalCustomProp,
  ...props
}: Props<OptionType, IsMulti, GroupType> & CustomSelectAsyncProps) {
  return (
    <ReactSelectAsync {...props} />
  );
}

3
投票

你可以这样使用:

import React from 'react'
import { omit } from 'lodash';
import Select, { GroupBase, Props } from 'react-select';

type SelectProps<Option, IsMulti extends boolean = false, Group extends GroupBase<Option> = GroupBase<Option>> = Props<Option, IsMulti, Group> & {
    label?: string;
    id?: string;
}

const SearchableSelect = <
    Option,
    IsMulti extends boolean = false,
    Group extends GroupBase<Option> = GroupBase<Option>
>(props: SelectProps<Option, IsMulti, Group>) => {
    const id = props.id || Math.random().toString()
    const reactSelectProps = omit(props, ['label', 'className'])

    return (
        <div>
            {props.label && (
                <label htmlFor={id} className="block text-sm font-medium text-gray-700">
                    {props.label}
                </label>
            )}
            <Select
                {...reactSelectProps}
                theme={(theme) => ({
                    ...theme,
                    colors: {
                        ...theme.colors,
                        primary: "var(--primary-500)",
                    },
                })}
            />
        </div>
    );
}


export default SearchableSelect


3
投票

即使在阅读了这里的一些答案后,我仍然在努力尝试这种方法。

这是我的完整方法:

首先,ReactSelect 的 props 没有一个干净的界面,类似于扩展 Html 按钮的方式,例如:

Interface IbuttonProps extends HTMLButtonElement

react-select props 默认 props 的接口名称为

Props
,可以从这两个路径导入:

import { Props } from "react-select/dist/declarations/src/Select" instead import { Props } from "react-select"

只有后者

import { Props } from "react-select"
才是正确的

Props
接口也使用泛型,所以它看起来类似于:

Props<Option,IsMulti,Group>

为了扩展此接口,我们将使用带有类型参数默认值的泛型类型定义,如下所示:

type MyCustomSelectProps<Option, IsMulti extends boolean = false, Group extends GroupBase<Option> = GroupBase<Option>> = Props<
   Option,
   IsMulti,
   Group
>

因此,当我们创建自己的react-select Props扩展时,它将看起来像这样:

type MyCustomSelectProps<Option, IsMulti extends boolean = false, Group extends GroupBase<Option> = GroupBase<Option>> = Props<
    Option,
    IsMulti,
    Group
> & {
 MyCustomProperty:string;
 MyOtherCustomProperty:number;
};

结果:


import * as Select from 'react-select';
import { GroupBase } from 'react-select';
import { Props } from 'react-select';


type SelectProps<Option, IsMulti extends boolean = false, Group extends GroupBase<Option> = GroupBase<Option>> = Props<
    Option,
    IsMulti,
    Group
> & {
    MyCustomProperty:string;
    MyOtherCustomProperty:number;
};


export const Select = <Option, IsMulti extends boolean = false, Group extends GroupBase<Option> = GroupBase<Option>>(
    props: SelectProps<Option, IsMulti, Group>,
) => {
    return (<Select {...props}/>)
}

-4
投票

您可以直接从

Props
包导入
react-select
类型。您可能想要扩展它,以便要求
label
id
都被定义。

import React from "react";
import ReactSelect, { Props } from "react-select";

type SelectProps = Props & {
  id: string;
  label: string;
};

const Select: React.FC<SelectProps> = ({id, label, ...rest}) => {
  return (
    <div>
      <label htmlFor={id}>{label}</label>
      <div>
        <ReactSelect {id, ...rest} />
      </div>
    </div>
  );
};
© www.soinside.com 2019 - 2024. All rights reserved.