【发布时间】:2019-03-18 18:34:44
【问题描述】:
上下文
我有两个组件。一个组件的 props 继承自另一个组件的 props。
declare namespace Props {
interface Fruit {
price: number;
}
interface Banana extends Fruit {
curvature: number;
}
}
declare const Fruit: React.FC<Props.Fruit>;
declare const Banana: React.FC<Props.Banana>;
事实是:
-
React.FC被 React 定义为 props 的一个函数。 - 我们知道函数类型的返回类型是协变的,而参数类型是逆变的。 Source
问题
现在,当尝试在 TypeScript 3.4.0-rc 中将一个分配给另一个时,我们得到:
/**
* ✅ Compile-time error. Function arguments are contravariant.
*/
const fruit: typeof Fruit = Banana;
/**
* ✅ No error. Function arguments are contravariant.
*/
const banana: typeof Banana = Fruit;
/**
* ✅ No errors as expected.
*/
const one: React.ReactComponentElement<typeof Fruit> = <Fruit price={3} />;
/**
* ⁉️ No errors (but expected one). Now it's covariant.
*/
const two: React.ReactComponentElement<typeof Fruit> = <Banana price={3} curvature={15} />
/**
* ⁉️ No errors (but expected one). Now it's contravariant.
*/
const three: React.ReactComponentElement<typeof Banana> = <Fruit price={3} />
/**
* ✅ No errors as expected.
*/
const four: React.ReactComponentElement<typeof Banana> = <Banana price={3} curvature={15} />
问题
为什么two 和three 不会导致错误?
【问题讨论】:
-
我认为根本问题是
<Banana price={3} curvature={15} />的类型是什么。据我所知,类型始终是JSX.Element,即React.ReactElement<any, any>。因此,虽然存在表示类型化 jsx 元素的类型,但编译器似乎未使用它,但我认为编译器只是返回JSX.Element而无需费心做任何其他事情.. -
以及相关的 GitHub 票证:github.com/Microsoft/TypeScript/issues/14729
-
谢谢@TitianCernicova-Dragomir。我想知道这是否是理想的行为——这证明了这个故事还有更多内容。
-
我认为这是实施的行为。我提到的问题确实表明团队愿意对此进行改进。
标签: reactjs typescript