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
}