如何在带有 React 的 Typescript/JSX 中使用带有箭头函数的泛型?

IT技术 reactjs generics typescript lambda react-jsx
2021-05-19 09:24:11

使用 Typescript,在 Visual Studio 中输入“.ts”文件,考虑以下声明:

export const foo = <T>(myObject: T) => myObject.toString();

这很好用,类型检查很好,一切都很好。

现在将完全相同的代码放入用于 JSX 和 React 的“.tsx”文件中。

Intellisense 非常沮丧并抱怨,因为它试图将 <T> 变成 React JSX 元素。但我的意图是让编译器将其视为泛型类型指示符。

编译器抱怨:

[gulp-typescript] 17008 JSX 元素“T”没有相应的结束标记。

我尝试了许多语法解决方法,试图让 IDE 和编译器都让我摆脱 JSX 并强制编译器将 <T> 理解为泛型,就像没有使用 JSX 一样。但我找不到神奇的酱汁来做到这一点。

有比我更聪明的人能解决这个问题吗?

4个回答

当您只有一个类型参数时,TypeScript 不确定它是否可能是 JSX 开始标记。它必须选择一个,所以它与 JSX 一起使用。

如果您想要一个具有完全相同语义的函数,您可以明确列出以下约束T

const foo = <T extends {}>(myObject: T) => myObject.toString();

这打破了 TypeScript 的歧义,以便您可以使用泛型类型参数。它也具有相同的语义,因为类型参数始终具有 的隐式约束{}

不是很漂亮,但通常的解决方法是添加一个尾随逗号:

export const foo = <T,>(myObject: T) => myObject.toString();

我想不出办法来解决这个问题,并且很高兴你能学到一个。
但是,这是实现相同目标的不同方法:

export const foo = function<T>(myObject: T) { return myObject.toString(); }

编译器不会抱怨泛型。

我个人使用extends unknown. 对我来说听起来最安全

const foo = <T extends unknown>(myObject: T) => myObject.toString();