I've come across the following code which is a filter callback function on an array. I'm confused trying to understand what this function is doing and am trying to break it down into smaller bits to understand but I can't seem to get my head around it.
I'm trying to learn TypeScript and know some JS but the syntax is confusing for me.
Could someone please explain how this function would operate on an arrays inputs please? a sort of walk through of the syntax in this exampled would be helpful. Thanks.
const check = (Boolean as any) as <T>(
a: T | false | undefined | null | ''
) => a is T;
Similar to JavaScript, to pass a function as a parameter in TypeScript, define a function expecting a parameter that will receive the callback function, then trigger the callback function inside the parent function.
In functions, parameters are the values or arguments that passed to a function. The TypeScript, compiler accepts the same number and type of arguments as defined in the function signature. If the compiler does not match the same parameter as in the function signature, then it will give the compilation error.
TypeScript supports the existing JavaScript function syntax for declaring and calling it within the program or the code snippet.
Ok, this function is kinda... crazy. Let's breakdown this code a bit.
First, take the following idiom as an example:
const something = ('' as any) as boolean
// something's type is boolean for Typescript, but its value is actually a string!
the (X as any) as Y
idiom is a hack that allows you to tell typescript that something is actually something else. You're taking full control of the type system, and Typescript won't be able to infer the underlying value - and much less catch it. It can lead to bugs, such as the above example where I tell TS that an empty string is a boolean.
Now, consider the next idiom:
const isTruthy: <T>( x: T | false | undefined | null | '' ) => x is T
// not yet implemented
This declaration tells typescript that "this is a function that takes any type of parameter, and if it returns true it means the parameter is definitely not falsy". This is done by using Type guards through the return type "x is T". This is useful because it'll allow you to take a possible-falsy value and verify that it is, in fact, not falsy:
const a: any[] | null | undefined = [];
if(isTruthy(a)) {
// a is any[]
}
One very simple way to implement isTruthy
is by using the Boolean
function:
type Falsy = null | undefined | false | 0 | ''
function isTruthy<T>(value: T | Falsy): value is T {
return Boolean(value);
}
So, whats the point?
let's take a look at your example once again:
const check = (Boolean as any) as <T>(
a: T | false | undefined | null | ''
) => a is T;
Boolean
in this code is a value. Specifically, it's the Boolean Function.any
and then cast to <T>( x: T | false | undefined | null | '' ) => x is T
So, all this code does is declare an alias for the Boolean
function and tell TS that it is a type guard where if check(a)
returns true, then a
is not falsy.
Or you could, you know, just check the value itself:
type Falsy = null | undefined | false | 0 | ''
const a: string | Falsy = 'test'
if (a) {
// a is inferred to be just "string"
}
your "check" function does some clever trickery to reuse the Boolean
function to do exactly what a simple if()
can already do.
Just check the truthiness of a value with if(value)
and move on
I missed an important part of the question:
Could someone please explain how this function would operate on an arrays inputs please? a sort of walk through of the syntax in this exampled would be helpful. Thanks.
in that case, your check
function can be used with the filter
method for some nice type inference:
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
});
This is because Typescript can't tell that the Boolean function also works just fine as a guard. So that's the one good use-case for your check
function, though I'd rename it to isTruthy
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With