2

How do you set a union type for a callback function or boolean? I tried this, but I got:

export interface IActions {
  dragend?: ((m:any)=>void) | boolean;
  click?:  ((m:any)=>void) | boolean;
  dblclick?:  ((m:any)=>void) | boolean;
}


    // using the following type guard in code
    // also tried `this.setting.click instanceof Function`
    if (typeof this.setting.click != 'boolean'){
      this.setting.click(m);
    } else {
      // default action
    }

Error:

error TS2349: Cannot invoke an expression whose type lacks a call signature. Type 'boolean | ((m: any) => void)' has no compatible call signatures.

1
  • 1
    What are your compiler settings, without strictnullchecks your code works, with strict null checks I get a different error then yours. Commented Oct 16, 2018 at 10:14

1 Answer 1

1

You can use type guards to create if statements that automatically type variables for you.

One way to write these guards would be:

(Forgive the naming ... I'm not feeling terribly creative today!)

type Action = (m: any) => void;
type ActionOrBoolean = Action | boolean;

function isActionOrBooleanAction(actionOrBoolean: ActionOrBoolean): actionOrBoolean is Action {
    return typeof actionOrBoolean != 'boolean';
}

function isActionOrBooleanBoolean(actionOrBoolean: ActionOrBoolean): actionOrBoolean is boolean {
    return typeof actionOrBoolean == 'boolean';
}

And they can be used like:

let v3: ActionOrBoolean = (Math.random() > 0.5)
  ? (p1: any) => {}
  : true;

if(isActionOrBooleanBoolean(v3)) {
    v3 = false;
} else if(isActionOrBooleanAction(v3)) {
    v3("");
}

Finally, here's a jsFiddle showing it all working.

writeLine("v1: " + v1);
writeLine("v1 isActionOrBooleanAction: " + isActionOrBooleanAction(v1));
writeLine("v1 isActionOrBooleanBoolean: " + isActionOrBooleanBoolean(v1));

writeLine("v2: " + v2);
writeLine("v2 isActionOrBooleanAction: " + isActionOrBooleanAction(v2));
writeLine("v2 isActionOrBooleanBoolean: " + isActionOrBooleanBoolean(v2));

// Example
let v3: ActionOrBoolean = (Math.random() > 0.5)
  ? (p1: any) => {}
  : true;

if(isActionOrBooleanBoolean(v3)) {
    v3 = false;
} else if(isActionOrBooleanAction(v3)) {
    v3("");
}

Output:

v1: true

v1 isActionOrBooleanAction: false

v1 isActionOrBooleanBoolean: true

v2: function (p1) { }

v2 isActionOrBooleanAction: true

v2 isActionOrBooleanBoolean: false

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.