Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript: declare return type to be dependent on argument value?

Tags:

typescript

I have the following function call:

this.get('barcode').scan();

Is it possible to define the get function in a way that the return type is determined by the value of the function argument. In my case 'get' returns the Barcode class if called with 'barcode' and the Mqtt class if called with 'mqtt'.

like image 498
rogergl Avatar asked Jun 26 '15 10:06

rogergl


People also ask

How do I specify a return type of function in TypeScript?

To define the return type for the function, we have to use the ':' symbol just after the parameter of the function and before the body of the function in TypeScript. The function body's return value should match with the function return type; otherwise, we will have a compile-time error in our code.

What does () => void mean TypeScript?

The syntax (a: string) => void means “a function with one parameter, named a , of type string, that doesn't have a return value”. Just like with function declarations, if a parameter type isn't specified, it's implicitly any .

How do you define the return type of arrow function in TypeScript?

You can set the return type of an arrow function in TypeScript right after its parameters, e.g. const greet = (name: string): string => {} . Once a function's return type is set, the type checker alerts us if the function returns a value of a different type.


2 Answers

Yes, you can use overload on strings to do this. Example:

interface BarcodeScanner { scan(): number; }
interface Accelerometer { getAcceleration(): number; }

class MyClass {
    get(name: 'accelerometer'): Accelerometer;
    get(name: 'barcode'): BarcodeScanner;
    get(name: string): any; // Fallback string signature
    get(name: string): any { // Implementation signature, not visible
        /* ... */
        return undefined;
    }

    something() {
        let x = this.get('barcode');
        x.scan(); // OK
        let y = this.get('accelerometer');
        y.getAcceleration(); // OK
    }
}
like image 79
Ryan Cavanaugh Avatar answered Dec 02 '22 04:12

Ryan Cavanaugh


It's not possible to statically determine a type in function of a (dynamic) string. But generics are made for these cases.

Example:

class MyClass {
    public get<T>(type: string): T {
        // ...
    }
    public anotherMethod() {
        this.get<Barcode>('barcode').scan();
    }
}

I'm not sure to understand the problem with Ember, but if the method get is dynamically inserted in the object, then maybe a solution like this:

class MyClass {
    public get: function<T> (type: string): T; // this is just a static declaration, there is no generated JS code here

    public anotherMethod() {
        this.get<Barcode>('barcode').scan();
    }
}
like image 28
Paleo Avatar answered Dec 02 '22 04:12

Paleo