The inline function is meant to be used only by hof, so TS can infer it's type safely.
But when the function is defined elsewhere and it's reference is passed to hof, TS cannot assume that the function is only meant to be used by hof because it can be used in other places as well. The only thing TS wants now is that the function that is being passed to hof is type compatible with what hof expects, in other words the type of the function being passed should be compatible with type: (a: string) => string.
And this becomes more clear when you observe the complaint by TS, the complaint is not at all related to hof, even if you remove all the other code and just have the someFunc function definition, TS would still be complaining, so there's no association between someFunc and hof and TS is simply complaining because of the implicit any type that the parameter a gets (refer to the --noImplicitAny compiler option).
If you explicitly state that argument a could be of type any, then there would be no complaints because (a: any) ⇒ string is compatible with (a: string) => string.
Finally, let's consider the following example:
function hof1(cb: (a: string) => string): void {}
function hof2(cb: (a: number) => string): void {}
function someFunc(a: string | number): string {
return `${a}`;
}
hof1((a) => a.toUpperCase());
hof2((a) => a.toFixed(2));
hof1(someFunc);
hof2(someFunc);
In the example someFunc is being used for both hof1 and hof2, so it makes it more clear why TS wasn't able to make any assumption, because someFunc is more generic as compared to what either hof1 or hof2 accepts. But with that inline function TS knew that it's exactly what hof accepts because that's the only place it can be used.