TSX/JSX项目中的可选JSX道具

Tyl*_*ian 14 jsx typescript reactjs react-tsx

我有一个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 />
  }
}
Run Code Online (Sandbox Code Playgroud)

// ComponentB.js
const ComponentB = ({ children, className, equalWidth }) => {
  return (...)
}
Run Code Online (Sandbox Code Playgroud)

有没有办法向TS发信号通知JSX组件道具都是可选的?

Tha*_*ara 10

一个最简单的选择是为你的可选道具设置一个默认值。例如,如果className是可选的,您可以将您的更改ComponentB.js为这样的。

const ComponentB = ({ children, className="", equalWidth }) => {
  return (...)
}
Run Code Online (Sandbox Code Playgroud)

此外,如果你在函数体中解构你的 props 而不是签名 TS 不会抱怨打字。

const ComponentB = (props) => {
  const { children, className, equalWidth } = props;
  return (...)
}
Run Code Online (Sandbox Code Playgroud)


Tom*_*ech 7

假设它ComponentB.js最终将作为TypeScript组件:

interface ComponentBProps {
    children?: ReactNode;
    className?: string;
    equalWidth?: boolean;
}

const ComponentB = ({ children, className, equalWidth }: ComponentBProps) => {
    // 
};
Run Code Online (Sandbox Code Playgroud)

在所有属性都是可选的特殊情况下,您可以?从界面上的每个属性中删除并使用Partial<ComponentBProps>,但我想至少某些东西最终会成为必需的道具.


如果你想保持ComponentB.js原样,那么另一种解决方案是创建一个类型定义文件:

import { ReactNode, StatelessComponent } from "react";

interface ComponentBProps {
    children?: ReactNode
    className?: string;
    equalWidth?: boolean;
}

export const ComponentB: StatelessComponent<ComponentBProps>;
Run Code Online (Sandbox Code Playgroud)

如果您将此文件放在与JavaScript文件相同的目录中ComponentB.d.ts,那么您应该可以ComponentB在TypeScript文件中导入.

我写的定义方式假定组件是一个名叫出口,而不是默认,即是出口像export const ComponentB.js的文件.

(可能)工作示例:https://github.com/fenech/tsx-jsx