针对TypeScript 2.1更新
TypeScript 2.1现在支持对象扩展/静止,因此不再需要任何变通办法!
原始问题
TypeScript支持JSX spread attributes,它通常在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" />
但是,React引入了一个warning if you pass any unknown props to an HTML element。上面的示例将生成一个React运行时警告,指出textToDisplay
是<a>
的未知属性。对于类似此示例的情况,建议的解决方案是使用object rest properties提取自定义属性,并将其余属性用于JSX spread属性:
const {textToDisplay, ...htmlProps} = this.props;
return (
<a {...htmlProps}>{textToDisplay}</a>
);
但是TypeScript还不支持这种语法。我知道希望有一天we will be able to do this in TypeScript。(更新:TS 2.1现在支持对象扩展/静止!为什么你还在阅读这篇文章?*)同时,有什么解决方法吗?我正在寻找一种不损害类型安全的解决方案,但发现它非常困难。例如,我可以这样做:
const customProps = ["textDoDisplay", "otherCustomProp", "etc"];
const htmlProps:HTMLAttributes = Object.assign({}, this.props);
customProps.forEach(prop => delete htmlProps[prop]);
但是这需要使用字符串属性名,而这些属性名没有经过实际属性的验证,因此容易出现拼写错误和糟糕的IDE支持。有没有更好的方法可以做到这一点?
9条答案
按热度按时间2uluyalo1#
实际上,它比上面所有的答案都简单,你只需要按照下面的例子来做:
希望这对你有帮助。
cunj1qz12#
您可能无法避免使用
this.props
的属性子集创建新对象,但可以使用类型安全来实现这一点。例如:
使用
LinkPropsKeys
对象(需要与LinkProps
匹配)将帮助您保持接口和运行时查找之间的键同步。ljsrvy3e3#
上面示例中的React.HtmlAttributes现在是泛型的,因此我需要从
React.AnchorHTMLAttributes<HTMLAnchorElement>
进行扩展。示例:
ubby3x7f4#
使用
...rest
yshpjwxd5#
像这样的吸气剂可以工作:
lymgl2op6#
对于那些可能不能很快理解
[x:string]: any;
在可接受答案中的作用的人:虽然它很像数组的语法,但它确实指定了一个对象,它的键是string
类型,它的值是any
类型,在TypeScript的术语中,它被称为“Index Signature“。但是,还要注意,有时候,作为一种替代的、对类型不太宽松的解决方案,您正在使用的库可能也导出了类型,因此您可以使用这些类型。
例如,在扩展Ant的按钮时,可以执行以下操作:
注意1:
IButtonProps & NativeButtonProps
中的&操作符只是在TypeScript中“合并”类型。现在,您不会失去Ant Button属性在您自己的Button上的智能,因为您不再使用any
。Ant Button的类型和您的IButtonProps是组合的,因此两者都存在。**注意2:**您可能也想知道我在哪里找到这个型别。这个型别是汇出到这里:https://github.com/ant-design/ant-design/blob/master/components/button/button.tsx#L124而且它的包含路径也可以使用intellisense实现,只要开始输入NativeButton...它一定会向你建议。
guicsvcw7#
我接受了尼岑·托默的答案,因为这是我的基本想法。
作为一个更一般化的解决方案,我最终选择了:
所以我可以这样使用它:
一旦TypeScript支持对象静止/扩展,我就可以查找
rest()
的所有用法,并将其简化为const {a, b, c, ...htmlProps} = props
。zf2sa74q8#
如果你把...rest参数作为参数传递给你的组件,TypeScript现在会忽略它。在我看来...rest参数不需要类型安全,因为它们是由父组件传递给子组件的默认参数。例如redux将有关存储的信息传递给子组件,所以...rest参数总是在那里,不需要类型安全或propTypes。
强文本
0wi1tuuw9#
React.ComponentPropsWithoutRef
/React.ComponentPropsWithoutRef
如https://react-typescript-cheatsheet.netlify.app/docs/advanced/patterns_by_usecase/中所述
如果使用
forwardRef
,请改用React.ComponentPropsWithRef
DEMO