泛型箭头函数 in tsx

长久以来一直坚持用 TS 写各类 Web 应用,一个重要的乐趣就是 TS 的 Intellisence 在 VSCode 中自动提示做的特别好,甚至比其他真正的强类型语言例如 Java or Golang 都做的好。

而泛型 (Generic)是 Typescript 的一个很有用的语言特性,能够少写很多的模板代码,避免通过复制大段代码来复用功能或者逻辑。

举个例子

方法很简单,就是检查一下传入的参数是不是存在,是就返回 true,否则返回 false

image-20210106011828726

在 React 中,Generic 遇到一个问题,就是 vscode 一直不停的提示语法错误。经过研究,发现原因就是 TS 编译器将泛型和 tsx 的组件标签没能正确的区分开来 (尖括号有歧义了)。有以下这么几个办法可以让泛型在 tsx 中和平共存。

Extends

泛型添加类型继承约束可以让编译器明确知道这是一个泛型声明。做法如下,

export const isPresentSomeObject = <T extends unknown>(t: T) => { if (t && Object.keys(t as any).length > 0) { return true } return false }

T extens unkonwn 的原因是所有的类型都可以赋值给到 unknown。另外, any 也可以起到同样的作用,但是用 any 就不再是类型安全的了。

Comma

另外一个小技巧就是在泛型中添加一个逗号,

export const isPresentSomeObject2 = <T,>(t: T) => { if (t && Object.keys(t).length > 0) { return true; } return false; };

这个语法实际上原本是用来定义多个泛型参数的,但是即便是不再继续写第二个泛型参数,也不会报错。通过这个逗号的添加,让编译器明白了这里是一个泛型,而不是 React 组件。因为 React 的标签是不支持写逗号的。

Normal function

最后一个办法就是不用箭头函数,回退到普通的函数声明中。

export function isPresentSomeObject3<T>(t: T): boolean { if (t && Object.keys(t).length > 0) { return true; } return false }

看起来,这是最没有歧义的一个方法了,编译器对于这样的写法是非常的认可。也算一个不是技巧的技巧吧 (是不是所谓的大智若愚)。

© 2021, XZD