Дополнительные подставки 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 являются необязательными?

Ответы

Ответ 1

Предполагая, что 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, а не по умолчанию, то есть экспортируется как export const ComponentB в файле .js.

(возможно) рабочий пример: https://github.com/fenech/tsx-jsx

Ответ 2

Один из самых простых вариантов - установка значения по умолчанию для ваших дополнительных реквизитов. В качестве примера, если className является необязательным, вы можете изменить свой ComponentB.js на что-то вроде этого.

const ComponentB = ({ children, className="", equalWidth }) => {
  return (...)
}

Также, если вы деконструируете свои реквизиты в теле функции вместо сигнатуры, TS не будет жаловаться на типизацию.

const ComponentB = (props) => {
  const { children, className, equalWidth } = props;
  return (...)
}