Reputation: 2357
I have a code, that is totaly OK from the human perspective. But it looks like typescript type system have hard time to understand it. Is there a smart way to hint compiler that everything is fine in that line?
const isMustToRun: boolean = isFunc(condition) ? condition() : condition;
code:
export const noop = function() {
};
export const isFunc = function(obj: any): boolean {
return typeof obj === 'function';
};
/**
*
* @param func funtion to run
* @param condition condition check
* @param args
*/
export const runIf = function f(condition: (Function | boolean), func: Function, ...args: any[]) {
return () => {
const isMustToRun: boolean = isFunc(condition) ? condition() : condition;
return isMustToRun ? func(...args) : noop();
};
};
If I wrote
typeof condition === 'function'
instead of "isFunc" call, then it works. But I don't want to repeat the code..
Upvotes: 3
Views: 216
Reputation: 250106
You need to transform isFunc
in a custom type guard and your code will work as expected.:
export const isFunc = function(obj: any): obj is Function {
return typeof obj === 'function';
};
I would recommend not using Function
though as it is not really very type safe, you can tighten up the function type with a function signature, and use the Extract
conditional type to preserve the actual type of the passed in function to the isFunc
type-guard:
export const isFunc = function<T>(obj: T): obj is Extract<T, Function> {
return typeof obj === 'function';
};
export const runIf = function f(condition: ((()=> boolean) | boolean), func: Function, ...args: any[]) {
return () => {
const isMustToRun: boolean = isFunc(condition) ? condition() : condition;
return isMustToRun ? func(...args) : noop();
};
};
Or a fully type safe version of runIf
that checks the args
agains the func
parameters:
export const runIf = function f<T extends (...a: any)=>any>(condition: ((()=> boolean) | boolean), func: T, ...args: Parameters<T>): (()=>ReturnType<T>) {
return () => {
const isMustToRun: boolean = isFunc(condition) ? condition() : condition;
return isMustToRun ? func(...args as any[]) : noop();
};
};
function testFn(n: string) : number { return +n;}
runIf(true, testFn, "0"); //ok
runIf(true, testFn, 0); //err
Upvotes: 2
Reputation: 276115
Change the return type of
export const isFunc = function(obj: any): boolean {
return typeof obj === 'function';
};
to be is Function
export const isFunc = function(obj: any): obj is Function {
return typeof obj === 'function';
};
This is called a user defined type guard 🌹
Upvotes: 4