Дополнительные реквизиты JSX в проекте TSX/JSX
У меня есть проект React, который я конвертирую из JS в TS. Проблема, с которой я сталкиваюсь, заключается в том, что TSX React предполагает, что все свойства, определенные в функциональном компоненте, являются обязательными.
// ComponentA.tsx
class ComponentA extends React.Component<any, any> {
render() {
/* Type '{ equalWidth: true; children: Element[]; }' is not assignable to type '{ children: any; className: any; equalWidth: any; }'.
* Property 'className' is missing in type '{ equalWidth: true; children: Element[]; }'.' */
return <ComponentB equalWidth />
}
}
а также
// ComponentB.js
const ComponentB = ({ children, className, equalWidth }) => {
return (...)
}
Есть ли способ сообщить TS, что все компоненты JSX являются опциональными?
2 ответа
Одним из самых простых вариантов будет установка значения по умолчанию для вашего дополнительного реквизита. В качестве примера, если className
необязательно, вы можете изменить свой ComponentB.js
что-то вроде этого.
const ComponentB = ({ children, className="", equalWidth }) => {
return (...)
}
Также, если вы деконструируете свой реквизит в теле функции вместо подписи, TS не будет жаловаться на набор текста.
const ComponentB = (props) => {
const { children, className, equalWidth } = props;
return (...)
}
При условии, что ComponentB.js
собирается закончить как компонент TypeScript:
interface ComponentBProps {
children?: ReactNode;
className?: string;
equalWidth?: boolean;
}
const ComponentB = ({ children, className, equalWidth }: ComponentBProps) => {
//
};
В особом случае, когда все свойства являются необязательными, вы можете удалить ?
от каждого свойства интерфейса и использования Partial<ComponentBProps>
, но я думаю, что по крайней мере что-то в конечном итоге будет необходимой опорой.
Если вы хотите сохранить ComponentB.js
как таковой, то альтернативным решением является создание файла определений типов:
import { ReactNode, StatelessComponent } from "react";
interface ComponentBProps {
children?: ReactNode
className?: string;
equalWidth?: boolean;
}
export const ComponentB: StatelessComponent<ComponentBProps>;
Если вы поместите в тот же каталог, что и файл JavaScript, и имя ComponentB.d.ts
тогда вы сможете импортировать ComponentB
в вашем файле TypeScript.
То, как я написал определение, предполагает, что компонент является именованным экспортом, а не по умолчанию, т.е. он экспортируется как export const ComponentB
в .js
файл.