Specify the Type of a Function
The answer here is pretty interesting.
You can declare a function type using this syntax:
(isFocused: boolean) => void
The isFocused
argument is a boolean, and we're returning void
.
This syntax can be used inline like this:
const addListener = (onFocusChange: (isFocused: boolean) => void) => {
Or it can be extracted to its own type like this:
type FocusListener = (isFocused: boolean) => void;
const addListener = (onFocusChange: FocusListener) => {
The Structure of a Function Type
The basic structure starts with the arguments and the return type, both of which can be whatever you want.
You can use undefined
for the return type, but then your function has to actually return undefined
.
For times when your function has no return value, you should use void
.
Using Function types
Here's an example of adding an isGreat
boolean as an additional argument:
type FocusListener = (isFocused: boolean, isGreat: boolean) => void;
Then whenever we called the FocusListener
we would have to include parameters for both:
const addListener = (onFocusChange: FocusListener) => {
onFocusChange(true, true)
}
We can also use function types in the same way we're used to using other types. Just be aware that your return types match appropriately.
const myFocusListener = (isFocused: boolean): void => {
// TypeScript error that `{}` is unassignable to void
return {}
}
Most of the time you're not going to need these types unless you're passing functions to other functions, or declaring the type of the function.
Transcript
The answer is pretty interesting. You can declare a function type using this syntax. Actually, if I go to the second solution, this second solution has extracted out to a type so it's a bit easier to read. We've got an isFocused argument to this function, which is a Boolean, and then we're returning void.
When you type a function here, if we just go from the top here, then the basic structure of this looks like this, where you have your arguments here and then you have the return type. If we wanted to, we can return, let's say, a string from here or an array of strings.
Then inside here, we would say const arrayOfStrings equals this. Then this will be typed as an array of strings. We change this to an array of numbers. There's our onFocusChange that we're passing into this other function. Then we get numbers here.
If your function returns nothing, you can either return undefined, or more likely, you should use void, because void is a special TypeScript type for expressing "This function returns absolutely nothing." If I just clear out some of this to just get that distinction a bit clearer.
If we wanted to return undefined here, and if I just add my isFocused Boolean back in, then we would have to actually return undefined from our function. Return undefined, and now it's happy with us. Whereas type void is not assignable to type undefined. If we use void, then it means we don't need to return anything from our function. That's why void is there.
Inside here, we can use all sorts of types that we've seen before. We can add multiple things if we want to. We can say isFocused, isGreat, which is a Boolean. Then every time we called onFocusChange here, we would also have to pass, "Is it great or not?" We can also use optional parameters here and do all of that fun stuff.
This is the basic syntax for how you declare a function type. This means, too, that we can just use this in the normal way that we used to with types by saying const myFocusListener is a FocusListener, and then you can just implement the type here.
If you return something which is not assignable to avoid, it's actually not going to yell at you because it treats that function as though it's returning void. What that means is you can pass anything to it and it's not going to care about it.
Most of the time, you're not going to need these types except when you're passing functions to other functions or trying to declare the type of a function. You can also do it here, too. It's usually a bit nicer just to say isFocused Boolean and then say void inside here, because if we return it now, then it's going to say type blur is not assignable to type void.
This syntax is really useful when you want to pass functions into other functions. Less useful when you want to declare a function from outside because it's a little bit less precise.