Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/26.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reactjs React中rest道具的TypeScript变通方法 更新了TypeScript 2.1_Reactjs_Typescript - Fatal编程技术网

Reactjs React中rest道具的TypeScript变通方法 更新了TypeScript 2.1

Reactjs React中rest道具的TypeScript变通方法 更新了TypeScript 2.1,reactjs,typescript,Reactjs,Typescript,,因此不再需要解决方法 原始问题 TypeScript支持在React中将HTML属性从组件传递到呈现的HTML元素时常用的类型: interface LinkProps extends React.HTMLAttributes { textToDisplay: string; } class Link extends React.Component<LinkProps, {}> { public render():JSX.Element { return (

,因此不再需要解决方法


原始问题 TypeScript支持在React中将HTML属性从组件传递到呈现的HTML元素时常用的类型:

interface LinkProps extends React.HTMLAttributes {
  textToDisplay: string;
}

class Link extends React.Component<LinkProps, {}> {
  public render():JSX.Element {
    return (
      <a {...this.props}>{this.props.textToDisplay}</a>
    );
  }
}

<Link textToDisplay="Search" href="http://google.com" />
但是TypeScript还不支持这种语法。我知道,希望有一天。(更新:!你为什么还在读这篇???)与此同时,有哪些解决办法?我正在寻找一种不会影响类型安全性的解决方案,并发现它异常困难。例如,我可以这样做:

const customProps = ["textDoDisplay", "otherCustomProp", "etc"];
const htmlProps:HTMLAttributes = Object.assign({}, this.props);
customProps.forEach(prop => delete htmlProps[prop]);

但这需要使用字符串属性名,而这些属性名不会根据实际的道具进行验证,因此容易出现拼写错误和糟糕的IDE支持。有更好的方法吗?

您可能无法避免使用
this.props
的属性子集创建新对象,但您可以使用类型安全性来实现这一点

例如:

interface LinkProps {
    textToDisplay: string;
}

const LinkPropsKeys: LinkProps = { textToDisplay: "" };

class Link extends React.Component<LinkProps & React.HTMLAttributes, {}> {
    public render(): JSX.Element {
        return (
            <a { ...this.getHtmlProps() }>{ this.props.textToDisplay }</a>
        );
    }

    private getHtmlProps(): React.HTMLAttributes {
        let htmlProps = {} as React.HTMLAttributes;

        for (let key in this.props) {
            if (!(LinkPropsKeys as any)[key]) {
                htmlProps[key] = this.props[key];
            }
        }

        return htmlProps;
    }
}
接口链接道具{
textToDisplay:字符串;
}
const LinkPropsKeys:LinkProps={textToDisplay:”“};
类链接扩展了React.Component{
public render():JSX.Element{
返回(
{this.props.textToDisplay}
);
}
私有getHtmlProps():React.HTMLAttributes{
让htmlProps={}作为React.HTMLAttributes;
for(让我们输入此.props){
如果(!(LinkPropsKeys as any)[key]){
htmlProps[key]=这个.props[key];
}
}
返回htmlProps;
}
}

使用
LinkPropsKeys
对象,它需要匹配
LinkProps
,将帮助您保持界面和运行时查找之间的键同步。

我接受了Nitzen Tomer的答案,因为这是我的基本想法

作为一个更一般化的解决方案,这就是我最终的结论:

export function rest(object: any, remove: {[key: string]: any}) {
  let rest = Object.assign({}, object);
  Object.keys(remove).forEach(key => delete rest[key]);
  return rest;
}
所以我可以这样使用它:

const {a, b, c} = props;
const htmlProps = rest(props, {a, b, c});

一旦TypeScript支持对象rest/spread,我就可以查找
rest()
的所有用法,并将其简化为
const{a,b,c,…htmlProps}=props

React.HtmlAttributes在上面的示例中现在是通用的,所以我需要从
React.AnchorHTMLAttributes
扩展

例如:

import React from 'react';

type  AClickEvent = React.MouseEvent<HTMLAnchorElement>;

interface LinkPropTypes extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
    to: string;
    onClick?: (x: AClickEvent) => void;
}

class Link extends React.Component<LinkPropTypes> {
  public static defaultProps: LinkPropTypes = {
    to: '',
    onClick: null,
  };

private handleClick = (event: React.MouseEvent<HTMLAnchorElement>) => {
   ...
    event.preventDefault();
    history.push(this.props.to);
 };

  public render() {
    const { to, children, ...props } = this.props;
    return (
      <a href={to} {...props} onClick={this.handleClick}>
        {children}
      </a>
    );
    }
}

export default Link;
从“React”导入React;
类型AClickEvent=React.MouseEvent;
接口LinkPropTypes扩展React.AnchorHtmlatAttributes{
到:字符串;
onClick?:(x:AClickEvent)=>void;
}
类链接扩展了React.Component{
公共静态defaultProps:LinkPropTypes={
至:'',
onClick:null,
};
私有handleClick=(事件:React.MouseEvent)=>{
...
event.preventDefault();
历史。推(这个。道具。到);
};
公共渲染(){
const{to,children,…props}=this.props;
返回(
);
}
}
导出默认链接;

像这样的getter可以工作:

class Link extends React.Component<{
  textToDisplay: string;
} & React.HTMLAttributes<HTMLDivElement>> {

  static propTypes = {
    textToDisplay: PropTypes.string;
  }

  private get HtmlProps(): React.HTMLAttributes<HTMLAnchorElement> {
    return Object.fromEntries(
      Object.entries(this.props)
      .filter(([key]) => !Object.keys(Link.propTypes).includes(key))
    );
  }

  public render():JSX.Element {
    return (
      <a {...this.HtmlProps}>
        {this.props.textToDisplay}
      </a>
    );
  }
}

<Link textToDisplay="Search" href="http://google.com" />
类链接扩展了React.Component{
静态类型={
textToDisplay:PropTypes.string;
}
private get HtmlProps():React.HTMLAttributes{
返回Object.fromEntries(
Object.entries(this.props)
.filter(([key])=>!Object.keys(Link.propTypes).includes(key))
);
}
public render():JSX.Element{
返回(
{this.props.textToDisplay}
);
}
}

这实际上比上面所有的答案都简单。您只需遵循以下示例:

type Props = {
  id: number,
  name: string;
  // All other props
  [x:string]: any;
}

const MyComponent:React.FC<Props> = props => {
  // Any property passed to the component will be accessible here
}
类型道具={
身份证号码:,
名称:字符串;
//所有其他道具
[x:字符串]:任意;
}
常量MyComponent:React.FC=props=>{
//传递给组件的任何属性都可以在此处访问
}

希望这有帮助。

使用
…rest

类型按钮按钮={
禁用:布尔值;
};
功能按钮(props:ButtonProps):JSX.Element{
const{disabled=false,…rest}=props;
...
返回(

..
很好的建议,这很有帮助。请注意,您正在寻找的语法现在是available@KyleGobel是的,我非常高兴。:)这个问题应该被删除吗?“TypeScript 2.1现在支持对象扩展/休息,因此不再需要任何解决方法!”你如何使用它?!@gyozokudor只需使用TypeScript 2.1或更高版本(现在是3.4了!)并使用原始示例:
const{textToDisplay,…htmlProps}=this.props
谢谢,但我认为您误解了错误。这不是TypeScript编译错误,而是传递(通过JSX扩展语法)导致的React运行时错误无法识别的HTML元素的属性,如上例中
标记上的
textToDisplay
。无论如何,TS 2.1添加对对象rest/spread语法的支持早已解决了这一问题。但您如何实际推断传递给
按钮的内容实际上是有效的HTML道具或事件?
type Props = {
  id: number,
  name: string;
  // All other props
  [x:string]: any;
}

const MyComponent:React.FC<Props> = props => {
  // Any property passed to the component will be accessible here
}