TypeScript 2.1现在支持对象散布/休息,因此不再需要任何解决方法!
TypeScript支持JSX扩展属性,该属性通常在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" />
但是,如果您将任何未知的prop传递给HTML元素,React都会发出警告。上面的示例将产生一个React运行时警告,它textToDisplay是的未知属性<a>。对于类似此示例的情况,建议的解决方案是使用对象其余属性提取您的自定义道具,并将其余用于JSX传播属性:
textToDisplay
<a>
const {textToDisplay, ...htmlProps} = this.props; return ( <a {...htmlProps}>{textToDisplay}</a> );
但是TypeScript尚不支持此语法。 我知道希望有一天我们能够在TypeScript中做到这一点。( 更新 :TS 2.1现在支持对象散布/静止!为什么仍要阅读此内容?)同时有一些解决方法?我正在寻找一种不会损害类型安全性的解决方案,并且发现它出奇的困难。例如,我可以这样做:
const customProps = ["textDoDisplay", "otherCustomProp", "etc"]; const htmlProps:HTMLAttributes = Object.assign({}, this.props); customProps.forEach(prop => delete htmlProps[prop]);
但是,这需要使用未经实际道具验证的字符串属性名称,因此容易产生错字和对IDE的不良支持。有没有更好的方法可以做到这一点?
您可能无法避免使用的属性的子集创建新对象this.props,但是可以使用类型安全性来做到这一点。
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; } }
使用LinkPropsKeys需要与匹配的object LinkProps可以帮助您使接口和运行时查找之间的键保持同步。
LinkPropsKeys
LinkProps