我期望它能起作用:
interface Point {
x: number;
y: number;
}
function A({x, y}: Point = {x: 1, y: 1}) {
return `x:${x}y:${y}`;
}
export default function App() {
return <A/>; //error TS2739
}
export default function App() {
return <>{A()}</>; //ok, no problem
}
为什么它不起作用?
ps. Stackoverflow 要求我添加一些详细信息,但我做不到,因为代码很好地解释了问题。这就是我添加此 ps 的原因。
该问题很可能是由于 React 中的默认参数和解构的工作方式而出现的。
当您调用不带参数的函数时
A()
,它会使用默认参数。但是当你使用 时
<A />
,React 会将一个空的 props 对象“{}”传递给 A。然后函数 A 接收这个空对象并尝试从中解构 x 和 y。但是由于 props 对象中缺少 x 和 y,因此它们的值将为undefined
。为了解决您的问题,您可以将值传递给您的组件
或者在界面中将 x 和 y 设置为可选
然后处理“A”组件函数中每个属性的未定义情况。
最后,您需要返回一个有效的 jsx 元素而不是字符串。
像这样:
当然,它不一定是 React fragment
当您编写 时
<A />
,它最终会A({})
以一个空对象作为参数进行调用;它不会在没有参数的情况下进行调用A()
。因此,您需要编写A
这样的代码,使其接受一个空对象并对其进行您想要的操作。在评论中,您暗示您要么想要同时要求x
和y
,要么想要同时禁止x
和y
。您不想让x
和成为y
独立的可选。如果是这样,那么你需要类似
请注意,TypeScript 没有像我们所说的那样表示“空对象”的类型。如果你像这样写
{}
,Point | {}
那么它将接受任何东西,因为{}
表示“没有已知属性的类型”,这与“已知没有属性的类型”不同。所以我们可以使用{x?: never, y?: never}
来表示一种类型,其中x
和y
要么缺失,要么undefined
。我的小ProhibitKeysOf<T>
工具类型只是为了展示如何在需要时将其扩展到更多属性。请注意,给出像 这样的默认参数
A
是没有意义的,因为永远不会在没有参数的情况下被调用。相反,您需要像上面那样的默认解构属性,这样当您传入 时,就会获得 的默认属性。从技术上讲,这意味着如果您传入 ,您将获得is和is ,而您并不想要这些……但注释排除了这种可能性。{x: 1, y: 1}
A
{x = 1, y = 1}
{}
x
y
1
{x: 2}
x
2
y
1
Point | EmptyObj
现在你可以
A
像这样调用:其中,您可以传入 both
x
或y
eitherx
nory
,如果您尝试只传入其中一个,则会出现错误。游乐场链接到代码