在TSX/JSX项目中的可选JSX属性

21

我有一个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组件的props都是可选的?


相关 - 组件上的可选属性 - vsync
2个回答

13

最简单的选择是为你可选的属性设置默认值。例如,如果className是可选的,你可以将你的ComponentB.js更改为以下内容。

一个简单的选择是为您的可选道具设置默认值。例如,如果 className 是可选的,则可以将 ComponentB.js 更改为以下内容。

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

如果您在函数体中分解道具而不是签名,TypeScript就不会在输入方面发出警告。

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

1
好的解决方案!问题在于TS假设如果你有onClick = null,则onClick的类型是字面量null - 而不是默认的null - Tyler Sebastian
我打算把悬赏给你。虽然这个解决方案不完全是我寻找的 - 存在一些问题(如我在上面的评论中描述的) - 但围绕它工作相对容易和直接。谢谢! - Tyler Sebastian
1
@TylerSebastian 如果它在某种程度上帮到了你,我很高兴。 - Tharaka Wijebandara

8
假设 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,那么你应该能够在 TypeScript 文件中导入ComponentB
我写的定义方式假设组件是一种命名导出,而不是默认导出,即它像.js文件中的export const ComponentB这样被导出。

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


1
嗯,是的和不是的:是的,ComponentB 最终会被转换为 TypeScript,但现在还没有。我无法为 .js 文件添加注释,因此无法添加 TS 类型 - 如果可能的话,我将能够正确地注释它。 - Tyler Sebastian
@Tyler 我做了一个小例子,使用了一个.d.ts文件,并添加了一个链接。 - Tom Fenech

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接