这不是 (现在 https://github.com/microsoft/TypeScript/issues/21699) 可能的。 JSX 的返回类型始终是JSX.Element
,非泛型类型。
解释
The JSX
命名空间提供类型和接口,告诉 TS 如何解释 JSX:存在哪些元素;哪些属性 和 可以与其各自的类型一起传递;组件函数和类的形状;并且,这里最相关的是,的返回类型JSX 工厂函数.
JSX 工厂函数
tsc
有一个名为jsxFactory https://www.typescriptlang.org/tsconfig#jsxFactory这需要一个string
。在反应中,这被设置为React.createElement
(这也恰好是该属性的默认值)。该属性给出了在使用 JSX 时调用的函数的名称。 JSX 实现者可以利用它来提供自定义 JSX 工厂函数,如下所示:
// Example for using JSX to create DOM elements:
function jsx(tag: JSX.Tag | JSX.Component,
attributes: { [key: string]: any } | null,
...children: Node[])
{
// Handle components:
if (typeof tag === 'function') {
return tag(attributes ?? {}, children);
}
type Tag = typeof tag;
const element: HTMLElementTagNameMap[Tag] = document.createElement(tag);
// ... here we assign properties and add children ...
return element;
}
然后我们要做的就是设置"jsxFactory": "jsx"
在我们的 tsconfig 中并导入jsx
在任何 .tsx 文件中(另请参阅:不带 React 的 Typescript JSX https://stackoverflow.com/questions/41557309/typescript-jsx-without-react/68238924).
所以,看起来我们应该能够在我们的泛型上进行一些类型推断jsx
函数来获取特定的返回类型,对吗?
JSX.Element
错误的。不幸的是,Typescript 采取了一些捷径(避免由于深层嵌套 JSX 导致编译器速度减慢); Typescript 没有使用工厂函数推断 JSX 的返回类型,而是使用JSX.Element
类型。这种类型是not通用:它可以是任何一件事:
namespace JSX {
type Element = Node;
}
那么,React 的定义是什么JSX.Element
?
namespace JSX {
interface Element extends React.ReactElement<any, any> { }
// ...
所以每JSX.Element
将React.ReactElement<any, any>
,无论元素或组件。
在您的示例中,我们可以像这样验证这一点:
type BannerType = ReturnType<typeof Banner>;
// Intellisense: type BannerType = JSX.Element
const div = <div />
type OtherType = typeof div;
// Intellisense: type OtherType = JSX.Element
注意:在撰写本文时,Typescript 的版本是 4.6.2。