如何在Typescript/JSX中与React一起使用箭头函数的泛型?

28
使用TypeScript,在Visual Studio中进行输入,将其输入到".ts"文件中,考虑以下声明:
export const foo = <T>(myObject: T) => myObject.toString();

这段代码工作得很好,类型检查也没有问题,一切都很棒。

现在把完全相同的代码放到一个用于JSX和React的".tsx"文件中。

Intellisense变得非常不满并且抱怨了,因为它试图将<T>转换为React JSX元素。但我的意图是让编译器将其视为通用类型标识符。

编译器会报错:

[gulp-typescript] 17008 JSX element 'T' has no corresponding closing tag.

我尝试了许多语法上的变通方法来让IDE和编译器都允许我逃离JSX,并强制将<T>理解为通用类型,就像如果没有使用JSX一样。但我找不到任何魔法般的方法来实现这一点。

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


请参见 https://dev59.com/QVwY5IYBdhLWcg3ws5oF#WbejEYcBWogLw_1bvd8w。 - tokland
4个回答

31

当您只有一个类型参数时,TypeScript 无法确定它是否可能是 JSX 开始标签。它必须选择一个,因此它选择了 JSX。

如果您想要具有完全相同语义的函数,则可以显式列出 T 的约束条件:

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

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


这是一个非常好的解决方案。谢谢。注意:Resharper错误地标记它为错误。但实际上并不是。 - Stephan G
6
不要使用此方法。现在(TS 3.5及以上版本),隐式约束为unknown:https://devblogs.microsoft.com/typescript/announcing-typescript-3-5/#generic-type-parameters-are-implicitly-constrained-to-unknown - ruohola

27

一个解决方法是在结尾添加逗号:

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

5

我个人使用extends unknown。听起来对我来说是最安全的选择。

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

0

我想不到解决这个问题的方法,如果你有好的方法也请告诉我,我会很高兴学习。
然而,这里有一种不同的方法来实现相同的目标:

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

编译器不会对泛型抱怨。


2
这确实可行,但当然它不会像箭头函数一样在所有方面表现,而且人们必须处理“this”的正确绑定。但是所有这些都说过了,这可能是唯一的解决方案。不幸的是! - Stephan G
在声明 export const 时,不存在 this 作用域。 - Nitzan Tomer

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