英文:
Typescript Error, React Higher order Component
问题
长期的React开发者尝试适应TypeScript。
在这个简单的高阶组件上,我遇到了正确的类型定义问题。
/**
* 返回一个带有默认类名集合的组件
*/
function withDefaultClasses<T extends JSX.IntrinsicAttributes>(
Component: React.FunctionComponent<T>,
defaultClassNames: string,
) {
type Props = T & { className?: string };
return function withClasses(props: T & { className?: string }) {
const { className, ...rest } = props;
// 在连接之前检查className是否存在
const classNames = className
? defaultClassNames + ' ' + className
: defaultClassNames;
return <Component className={classNames} {...rest} />;
};
}
我遇到了以下错误:
类型 '{ className: string; } & Omit<Props, "className">' 不能赋值给类型 'IntrinsicAttributes & T'。
类型 '{ className: string; } & Omit<Props, "className">' 不能赋值给类型 'T'。
'T' 可能会被赋予一个与 '{ className: string; } & Omit<Props, "className">' 无关的任意类型。
我认为这可能是因为泛型组件可能不能具有className属性。
我感到困惑,我原本期望不会看到TypeScript错误。
英文:
Long time React developer trying to adapt to typescript.
I am having issues getting the correct typing on this simple Higher order component
/**
* Returns a component that will have a default set of classnames
*/
function withDefaultClasses<T extends JSX.IntrinsicAttributes>(
Component: React.FunctionComponent<T>,
defaultClassNames: string,
) {
type Props = T & { className?: string };
return function withClasses(props: T & { className?: string }) {
const { className, ...rest } = props;
// Check if className is present or not before concatenating
const classNames = className
? defaultClassNames + ' ' + className
: defaultClassNames;
return <Component className={classNames} {...rest} />;
};
}
I am getting the following error
Type '{ className: string; } & Omit<Props, "className">' is not assignable to type 'IntrinsicAttributes & T'.
Type '{ className: string; } & Omit<Props, "className">' is not assignable to type 'T'.
'T' could be instantiated with an arbitrary type which could be unrelated to '{ className: string; } & Omit<Props, "className">'.
I believe it it due to the fact that the generic component could not have the className property perhaps.
I'm at a loss
I was expecting not to see Typescript errors
答案1
得分: 1
在这个高阶函数中,你试图扩展一个React组件,添加额外的props。你面临的问题是TypeScript不知道你提供的组件(Component
)是否接受className
prop。
你可以这样做,创建一个新类型,扩展T
并包含className
。像这样:
function withDefaultClasses<T extends React.ComponentProps<any>>(
Component: React.ComponentType<T>,
defaultClassNames: string,
) {
return function withClasses(props: T) {
const { className, ...rest } = props;
// 在连接之前检查className是否存在
const classNames = className
? defaultClassNames + ' ' + className
: defaultClassNames;
// 我们展开其余的props并添加我们连接的className
return <Component {...rest as T} className={classNames} />;
};
}
在上面的代码中,React.ComponentProps<any>
允许我们确保T
始终包括className
作为可能的属性。React.ComponentType<T>
是一个更通用的组件类型,允许包括函数和类组件。在其余的props上使用as T
断言可以让TypeScript理解这些属性是为组件而设计的。
这应该解决了TypeScript错误。它假设你要包装在withDefaultClasses
中的原始组件(或组件)可以接受className
prop。如果不是这种情况,你可能需要相应地调整类型或组件。
英文:
In this higher-order function, you're trying to extend a React component with additional props. The issue you're facing is that TypeScript doesn't know that the component you're providing (Component
) accepts a className
prop.
What you can do is to make a new type that extends T
and includes className
. Like this:
function withDefaultClasses<T extends React.ComponentProps<any>>(
Component: React.ComponentType<T>,
defaultClassNames: string,
) {
return function withClasses(props: T) {
const { className, ...rest } = props;
// Check if className is present or not before concatenating
const classNames = className
? defaultClassNames + ' ' + className
: defaultClassNames;
// We spread the rest props and add our concatenated className
return <Component {...rest as T} className={classNames} />;
};
}
In the above code, React.ComponentProps<any>
allows us to ensure T
always includes className
as a possible property. React.ComponentType<T>
is a more generic type for components, allowing for both function and class components. The as T
assertion on the rest props allows TypeScript to understand that the properties are meant for the Component.
This should resolve the TypeScript error. It assumes that the original component (or components) you are wrapping with withDefaultClasses
can accept a className
prop. If that's not the case, you may need to adjust the types or the components accordingly.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论