8

I have the following code.

interface MySecondInterface<A>{
    type: A;
}

interface MyInterface {
    (val1:string, val2:string): MySecondInterface<string>;
    (): MySecondInterface<string>;
}

const myInterfaceFn: MyInterface = (value1: string, value2:string) => {
    return {
        type: value1 + value2
    };
}



const myInterfaceFn2: MyInterface = () => {
    return {
        type: "Text"
    };
}

You can find the code here. I am getting error

Type '(value: string) => { type: string; }' is not assignable to type 'MyInterface'.

How will I create the interface to support both method signatures?

Basically, an interface for a function that takes either 2 arguments or no arguments. How can I do that?

3
  • Is making the val optional an option for you? Commented May 15, 2017 at 8:45
  • If you are trying to create a function that will accept both no parameters and a string parameter, you can define a single function with an optional val parameter. Commented May 15, 2017 at 9:00
  • I am trying to create a single interface which can be passed as a method argument, such a way that the argument can be invoked with three parameters or no parameter at all, in the example I used only one. I am updating example. Commented May 19, 2017 at 1:39

4 Answers 4

6
+25

What about using type instead of interface?

interface MySecondInterface<A>{
  type: A;
}

type MyInterface = ((val1: string, val2: string) => MySecondInterface<string>) | (() => MySecondInterface<string>);

const myInterfaceFn: MyInterface = (value1: string, value2:string) => {
  return {
    type: value1 + value2
  };
}

const myInterfaceFn2: MyInterface = () => {
  return {
    type: "Text"
  };
}
Sign up to request clarification or add additional context in comments.

2 Comments

I've changed type MyInterface to be: type MyInterface = ((val1: string, val2: string) => MySecondInterface<string>) | (() => MySecondInterface<number>); // second part is now (() => MySecondInterface<number>) (<number> not <string>) - all the other lines remain unchanged - but TypeScript does not complain (I would expect it to complain though). I'm wondering why ? Thanks !
it seems that: type MyInterface = ((val1: string, val2: string) => MySecondInterface<string>); is enough. The second part seems to be redundant for TypeScript.
4

Your myInterfaceFn has to satisfy both function definitions in MyInterface.

The following code works fine!

interface MySecondInterface<A>{
    type: A;
}

interface MyInterface {
    (val1:string, val2:string): MySecondInterface<string>;
    (): MySecondInterface<string>;
}

const myInterfaceFn: MyInterface = (value1: string = undefined, value2:string = undefined) => {
    return {
        type: value1 !== undefined && value2 !== undefined
            ? value1 + value2
            : "Text"
    };
}



const myInterfaceFn3: MyInterface = () => {
    return {
        type: "Text"
    };
}

Comments

3

Focus in on your error

Type '(value: string) => { type: string; }' is not assignable to type 'MyInterface'.

MyInterface instances must be allowed to take 0 arguments. So the following errors:

const myInterfaceFn: MyInterface = (value1: string, value2:string) => {
    return {
        type: value1 + value2
    };
}

But if you mark both as optional (e.g. using default parameters) the error goes away:

const myInterfaceFn: MyInterface = (value1 = '', value2 = '') => {
    return {
        type: value1 + value2
    };
}

1 Comment

Ah ... So to clarify, if you define an interface of function types (i.e., more than one), then any function assigned to a variable typed to that interface must satisfy >all< types? I can fix OP's error by changing the type to (val1?:string, val2?:string): MySecondInterface<string>; so I think that's correct.
1

I am not quite sure why TypeScript is ok with your interface declaration, because the two signatures have nothing in common. Maybe this is due to the fact how TypeScript handles function signatures (see sidenote below).

In your case, I would suggest

  • make the value optional or
  • create one function and use overloading, e.g.

interface Result {
    type: string;
}

function myFn();
function myFn(val?: string):Result {
    if (!val) { return { type: 'foo' }; }
    return { type: val };
}

Sidenote: TypeScript is a little bit weird when it comes to call signatures. I guess this is due to the fact that it wants to be a superset of JavaScript. The following snippets illustrates this:

interface Fn {
    (a: string): string;
}

const f1: Fn = () => 'hi';
const f2: Fn = (a: string) => a;

f1();       // Supplied parameters do not match any signature of call target.
f1('a');    // OK, even though `f1` has no explicit argument...
f2('asd');  // OK

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.