需要帮助理解令人困惑的Typescript函数
我遇到了以下代码,它是数组上的过滤器回调函数。我很困惑试图理解这个函数在做什么,我试图把它分解成更小的部分来理解,但我似乎无法理解它。
我正在尝试学习 TypeScript 并了解一些 JS,但语法让我感到困惑。
有人可以解释一下这个函数如何对数组输入进行操作吗?对本示例中的语法进行某种演练会有所帮助。谢谢。
const check = (Boolean as any) as <T>(
a: T | false | undefined | null | ''
) => a is T;
const check = (Boolean as any) as <T>(
a: T | false | undefined | null | ''
) => a is T;
回答
好吧,这个功能有点……疯狂。让我们稍微分解一下这段代码。
首先以下面的成语为例:
const something = ('' as any) as boolean
// something's type is boolean for Typescript, but its value is actually a string!
该(X as any) as Y
成语是一个黑客工具,允许你告诉打字稿的东西实际上是别的东西。您正在完全控制类型系统,而 Typescript 将无法推断出潜在的价值——更不用说抓住它了。它可能会导致错误,例如上面的示例,我告诉 TS 一个空字符串是一个布尔值。
现在,考虑下一个习语:
const isTruthy: <T>( x: T | false | undefined | null | '' ) => x is T
// not yet implemented
这个声明告诉打字稿“这是一个接受任何类型参数的函数,如果它返回真,则意味着该参数绝对不是假的”。这是通过返回类型“x is T”使用类型保护来完成的。这很有用,因为它允许您采用可能为假的值并验证它实际上不是假的:
const a: any[] | null | undefined = [];
if(isTruthy(a)) {
// a is any[]
}
一种非常简单的实现方法isTruthy
是使用该Boolean
函数:
type Falsy = null | undefined | false | 0 | ''
function isTruthy<T>(value: T | Falsy): value is T {
return Boolean(value);
}
那么,重点是什么?
让我们再看看你的例子:
Boolean
在这段代码中是一个值。具体来说,它是布尔函数。- 它被投射到
any
然后投射到<T>( x: T | false | undefined | null | '' ) => x is T
所以,所有这些代码所做的就是为Boolean
函数声明一个别名,并告诉 TS 它是一个类型保护,如果check(a)
返回true,则a
不是假的。
或者你可以,你知道,只是检查值本身:
type Falsy = null | undefined | false | 0 | ''
const a: string | Falsy = 'test'
if (a) {
// a is inferred to be just "string"
}
TL; 博士
你的“检查”函数做了一些巧妙的技巧来重用该Boolean
函数来完成一个简单的if()
已经可以做的事情。
只需检查一个值的真实性if(value)
并继续
<编辑>
我错过了问题的一个重要部分:
有人可以解释一下这个函数如何对数组输入进行操作吗?对本示例中的语法进行某种演练会有所帮助。谢谢。
在这种情况下,您的check
函数可以与该filter
方法一起使用以进行一些不错的类型推断:
const arr = ['a', false, 123, 0, '', null, undefined];
arr.filter(Boolean).forEach(value => {
// value is possibly falsy even though the `filter` makes sure it isn't
});
const check = (Boolean as any) as <T>(
a: T | false | undefined | null | ''
) => a is T;
arr.filter(check).forEach(value => {
// value is string | number | true
});
这是因为 Typescript 无法判断 Boolean 函数也可以很好地作为守卫。所以这是您的check
函数的一个很好的用例,尽管我将其重命名为isTruthy
.