我有一个按钮组件.我只需在我定义的许多可选props 中传递一个onClickprops :

const Button = (props: ButtonProps) => {
    const handleClick: React.MouseEventHandler<HTMLButtonElement | HTMLAnchorElement> = e => {
        props.onClick(e);
    }
    return (
        <StyledButton onClick={handleClick}>
            {props.children}
        </StyledButton>
    );
};

然后我就这样使用它:

<Button onClick={(e) => {
    console.log(e);
}}>Click me!</Button>

那么,根据前面提到的错误,对象怎么可能是未定义的呢?很明显,我正在将函数传递给它,而且根据类型定义也是如此.所以,我向它传递一个对象.很简单!

...
onClick?: React.MouseEventHandler<HTMLElement>
...

我最近在这个项目中增加了一些更严格的判断,相关的判断包括:

"strictFunctionTypes": true,
"strictNullChecks": true

strict:true已存在,但从未发生此错误.

这里有什么问题?

Update - Types added

export interface IBaseButtonProps {
    type?: ButtonType;
    disabled?: boolean;
    size?: ButtonSize;
    block?: boolean;
    loading?: boolean | { delay?: number };
    icon?: string;
    className?: string;
    prefixCls?: string;
    children?: React.ReactNode;
}

export type AnchorButtonProps = {
    href: string,
    target?: string,
    onClick: React.MouseEventHandler<HTMLElement>
} & IBaseButtonProps & Omit<React.AnchorHTMLAttributes<any>, 'type' | 'onClick'>;


export type NativeButtonProps = {
    onClick: React.MouseEventHandler<HTMLElement>,
    htmlType?: ButtonHTMLType
} & IBaseButtonProps & Omit<React.ButtonHTMLAttributes<any>, 'type' | 'onClick'>;

export type ButtonProps = Partial<AnchorButtonProps & NativeButtonProps>

笔记:

可能的解决方案是分解props 并添加默认props .或者使用defaultProps从react .但不确定我是否真的需要Typescript.

推荐答案

那么,根据上面提到的错误,对象怎么可能是未定义的呢?[原文如此]

export type ButtonProps = Partial<AnchorButtonProps & NativeButtonProps>左右使用Partial<T>导致onClick是可选的.当我们使用Partial<T>时,所有属性都会收到?,因此成为可选的,这意味着所有属性都可以不定义.

解决方法有两种:一种是将ButtonProps保持不变,将onClick作为可选选项,并在调用它之前判断onClick是否已定义(fix 1);另一个是将ButtonProps更改为需要onClick(修复2和3).

Fix 1: onClick remains optional

使用已有的ButtonProps,然后在调用它之前判断onClick是否已定义.这是你在 comments 中链接的代码中的what antd does.

const Button = (props: ButtonProps) => {
  const handleClick: React.MouseEventHandler<
    HTMLButtonElement | HTMLAnchorElement
  > = e => {
    if (props.onClick) props.onClick(e); // works
  };
};

Fix 2: onClick becomes required

通过不将Partial应用于NativeButtonProps来更改ButtonProps:

type ButtonProps1 = Partial<AnchorButtonProps> & NativeButtonProps;

const Button1 = (props: ButtonProps1) => {
  const handleClick: React.MouseEventHandler<
    HTMLButtonElement | HTMLAnchorElement
  > = e => {
    props.onClick(e); // works
  };
};

Fix 3: onClick becomes required too

定义一个RequireKeys类型,它允许您指定非可选的键.

type RequireKeys<T, TNames extends keyof T> = T &
  { [P in keyof T]-?: P extends TNames ? T[P] : never };

type ButtonProps2 = RequireKeys<ButtonProps, "onClick">;

const Button2 = (props: ButtonProps2) => {
  const handleClick: React.MouseEventHandler<
    HTMLButtonElement | HTMLAnchorElement
  > = e => {
    props.onClick(e); // works
  };
};

Mapped Types: removing optional modifier的答案有更多关于我如何定义RequireKeys<T>的信息.

Typescript相关问答推荐

为什么当类类型与方法参数类型不兼容时,该函数可以接受类类型

在TypScript中的同一数组中验证不同类型

如何根据服务响应构建子路由

发出与HTML多姆事件重叠的Angular事件

推断类型

创建一个将任意命名类型映射到其他类型的TypScript通用类型

在角形加载组件之前无法获取最新令牌

使用React处理Websocket数据

Webpack说你可能需要在Reactjs项目中增加一个加载器''

使某些(嵌套)属性成为可选属性

如何按不能保证的功能过滤按键?

适当限制泛型函数中的记录

对未到达受保护路由的路由环境做出react

用于验证字符串变量的接口成员

为什么&;(交集)运算符会删除不相交的属性?

使用泛型识别对象值类型

类型脚本-处理值或返回值的函数

TypeScrip-如何自动推断UNION变量的类型

基于泛型的类型脚本修改类型

通过函数传递确切的类型,但验证额外的字段