简体   繁体   中英

How to use an interface for function type declaration in type script

I am trying create a function type ( delegate ), by using following code.

interface DelegateTypeExample {
    m: (s: string) => number;
}

const someFunc: DelegateTypeExample = (s: string) => {
    return { m: null };
};

I keep getting following error, even though I am returning m in my object.

Property 'm' is missing in type '(s: string) => { m: any; }' but required in type 'DelegateTypeExample'.

Now I am able to get rid of the error by using:

interface DelegateTypeExample {
    (s: string): number;
}

const someFunc: DelegateTypeExample = (s: string) => {
    return 2;
};

But the moment I am adding another field to interface, it stops working, even thoug I am returning anotherField in the object.

interface DelegateTypeExample {
    (s: string): number;
    anotherField: string;
}

const someFunc: DelegateTypeExample = (s: string) => {
    return { x: 2, anotherField: '123' };
};

error:

Property 'anotherField' is missing in type '(s: string) => { x: number; anotherField: string; }' but required in type 'DelegateTypeExample'.

Just wanted to understand, why my code won't work, the way it is now.

Is it just a syntactic principle, I have to follow.

You are misunderstanding the role of the interface. When some object implements an interface, it must have all the fields and functions which the interface has. In an essence, the interfaces says "all object implementing me will have at least all of the stuff I'm declaring" - it's a contract between the interface and its users.

Now back to your examples:

interface DelegateTypeExample {
    // Your interface must have a function called m which takes a string and returns a number
    m: (s: string) => number; 
}

// You are saying that your someFunc is a function which takes a string
// and returns an object which has the field m.
const someFunc: DelegateTypeExample = (s: string) => {
    return { m: null };
};

As you can see from my comments, you are creating 2 very different types and that's why they are incompatible. Here's what the current definition of the interface is expecting:

const someObj: DelegateTypeExample = {
    m: (s: string) => 42
};

Moving on to your second example, it works because now you are saying that your interface is entirely a function - it doesn't have a function called m - the entire object must be a function. That's why it works.

Finally, your third example says that objects implementing the interface must:

  1. Be a function
  2. Have a anotherField property. Note that it's the function which has to have the property, and not its return value.

Here's how a valid object would look like for your third example.

// You can't add all fields of the type immediately since it needs to be a function
const someFunc: DelegateTypeExample = (s: string) => {
    return 42;
};
// Add the field
someFunc.anotherField = "Foo";

As a general tip, when creating objects that follow a certain interface, make sure that the object has exactly properties as the interface.

If you add field to your DelegateTypeExample you define a property to be assigned to the someFunc variable and not a return type of the sumeFunc function.

The following example would not throw an error:

interface DelegateTypeExample {
    (s: string): number;
    anotherField: string;
}

const someFunc: DelegateTypeExample = (s: string) => {
    return 2;
};

someFunc.anotherField = '123'˙;

Basically this is a way to add static fields to the function constructor, and it would be accessible through someFunc.anotherField .

If you want to add this field to the return value, you have to extend your return type:

interface DelegateTypeExample {
    (s: string): {x: number, anotherField: string;};
}

const someFunc: DelegateTypeExample = (s: string) => {
    return { x: 2, anotherField: '123' };
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM