Stevanicus
Stevanicus

Reputation: 7761

Extending and defining function signatures in TypeScript

Is it possible to assign a function signature to a name?

For example, some external module provides an interface

interface ExtFunctionInterface {
    (arg1: string, arg2: number): boolean
}

I would like to create a local interface or abstract class that assigns the above interface signature, to a method name. For example:

interface MyLocalInterface {
    someMethodName typeof ExtFunctionInterface 
}

or

abstract class MyLocalAbstractClass {
    public abstract someMethodName typeof|signature of ExtFunctionInterface 
}

So that when the interface is implemented or the class is extended:

class MyClass {implements|extends} MyLocal{Interface|AbstractClass} {

    // Correct impl
    public someMethodName(arg1: string, arg2: number): boolean {
        // impl
    }

    // Compiler would complain that the function is not implemented
    // correctly because "arg2" is missing or type is wrong for e.g.
    public someMethodName(arg1: string): boolean {
        // impl
    }

}

This means that when ExtFunctionInterface is changed, the compiler would notify that the signature is incorrect.

Upvotes: 0

Views: 3776

Answers (1)

Titian Cernicova-Dragomir
Titian Cernicova-Dragomir

Reputation: 249666

For interfaces, the answer is simpler then you might expect, just declare a field on the interface and you will get the desired behavior:

interface MyLocalInterface {
    someMethodName : ExtFunctionInterface 
}

class MyClassFromInterfce implements MyLocalInterface {
    // Will satisfy the interface 
    public someMethodName (arg1: string, arg2: number): boolean {
        return false;
    }
    // Will not satisfy the interface parameter is of the wrong type
    public someMethodName(arg2: number): boolean {
        return false;
    }
}

For abstract classes you can define an abstract field, unfortunately you can't implement it as a member function, you need to do it as a field containing the function, which should be an ok work around in most cases:

abstract class MyLocalClass {
    abstract get someMethodName() : ExtFunctionInterface 
}

class MyClass extends MyLocalClass {
    // Ok 
    public someMethodName  = (arg1: string, arg2: number): boolean => {
        return false;
    }
    // Not ok
    public someMethodName = (arg2: number): boolean => {
        return false;
    }
}

Note In the question you want the compiler to warn if there are fewer arguments, this is not the way typescript checks function compatibility (not just in this case, but in general). A function with fewer parameters will be compatible with a signature requiring more. Typescript will warn about argument type mismatch. For example :

class Base {
    method(arg1: string, arg2: number) {}
}
class Derived extends Base {
    // We can override with fewer parameters 
    method(arg1: string) {}
    // We can't override if parameter types are missmatched  
    method(arg1: number) {}

    // We can override with more parameres if they are optional  
    method(arg1: string, arg2: number, arg3?: number) {}
    // But not if they are required
    method(arg1: string, arg2: number, arg3: number) {}
}

Upvotes: 1

Related Questions