我有一小组组件,其中Wrapper
将通过cloneElement
向每个子组件注入一个prop来操作它的children
(因此称为Component
)。这里的问题是Component
prop是泛型类型。当我在代码中公开Component
时,我不希望它的某个prop出现在签名中。因为它将由Wrapper
组件自动注入。我有一个简明的例子来说明我的意思:types.ts
export type SomeObject = {
someKey: string;
};
type PropThatWillBeInjected<T extends SomeObject> = {
fn: (value: string) => T;
};
export type WannaBePropTypes = {
name: string;
};
export type PropTypes<T extends SomeObject> = PropThatWillBeInjected<T> &
WannaBePropTypes;
重要提示:PropTypes<T>
是Component
所期望的,但是作为一个程序员,我希望WannaBePropTypes
是这个组件的签名。
x1米11米1x
function Component<T extends SomeObject>(props: PropTypes<T>) {
const { fn, name } = props;
const result = fn(name);
return <div>Hello, {result.someKey}</div>;
}
export default Component;
Wrapper.tsx
function Wrapper(props: { children: ReactNode }) {
const { children } = props;
return (
<div id="wrapper">
{React.Children.map(
children as ReactElement<PropTypes<SomeObject>>,
(child, index) =>
cloneElement(child, {
...child.props,
fn: (value: string) => ({
someKey: `${value}-${index}`,
}),
})
)}
</div>
);
}
export default Wrapper;
正如预期的那样,当我尝试如下使用这些组件时,代码可以工作,但编译器会抱怨:
<Wrapper>
<Component name="Alice" />
<Component name="Bob" />
</Wrapper>
类型"{name:}"中缺少属性"fn"字符串;}",但在类型" PropThatWillBeInjected "中是必需的。(2741)
有没有办法强制转换Component
,这样我就不需要手动传递fn
了?我知道当 prop 类型不是泛型的时候有办法...
我尝试过的:
1.将fn
设置为可选:有效,但这不是我想要的解决方案;
1.用另一个组件 Package Component
并将noop
传递到Component
:工作,但我不想创建这个不必要的 Package 器;
具有以下示例代码的Playground:StackBlitz
1条答案
按热度按时间thtygnil1#
如果我没理解错的话,您希望将
Component
作为<Component name="Alice" />
调用,并且应该存在针对以下两种情况的内部逻辑:当fn
被传递时,如果是这样,你可以创建不必要的类型(而不是不必要的 Package 器),它将是WannaBePropTypes
或完整的属性之一。这就像你的try#1和try#2的某种组合:因此,在
Wrapper
组件中定义children as ReactElement<FullProps<SomeObject>>
之前,fn
是可选的。至于
Component
,我想你可以直接给FullProps
投 prop :但是如果出于某种原因需要更严格的代码,可以这样缩小
props
类型:尽管看起来这个条件在你的情况下总是假的。
这是 * 如何处理仅使用Typescript *。
顺便说一句:也许你可以把
WannaBePropTypes
对象的数组传递给Wrapper
而不是子对象?如果<Component name="Alice" />
本身什么也不做,这听起来会更好。