microsoft / TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://www.typescriptlang.org
Apache License 2.0
100.32k stars 12.39k forks source link

Cast Method of a class to a certain type #39623

Open tolotrasamuel opened 4 years ago

tolotrasamuel commented 4 years ago

Search Terms

casting type interface method function parameters inference class

Suggestion

Currently, it is impossible to infer the parameters and the return types of a method of a class using a type

The goal is to be able to declare a method without repeating the param types and the return type. I used typescript Type for that.

But there is currently no way to do this without changing the compiled javascript code.

type IBar = (x:number, y: number)=>number;

I tried

type IBar = (x:number, y: number)=>number;
class Foo {
    sum:IBar=(x,y)=>{
        return x+y;
    }
}

BUT unfortunately, this changes the javascript code compiled into:

class Foo {
    constructor() {
        this.sum = (x, y) => {
            return x + y;
        };
    }
}

I am looking for something that compiles into:

class Foo {
    sum(x, y) {
        return x + y;
    }
}

Another option currently is to declare an interface and implement it on the class like so:

interface IBar { sum(x: number, y: number): number; }

class Foo implements IBar {
    public sum(x: number, y: number): number {
        return x + y;
    }
}

HOWEVER, this approach would bnd the method name to only sum . What if I want to use the same method type with a different name like divide or multiply

Use Cases

It will be used like this

class Foo {
    sum(x,y){
        return x+y;
    } as IBar
}

Examples

class Foo {
    sum(x,y){
        return x+y;
    } as IBar
}

or

class Foo {
    divide(x,y){
        return x+y;
    } as IBar
}

or

class Foo {
    multiply(x,y){
        return x+y;
    } as IBar
}

Checklist

My suggestion meets these guidelines:

Barbiero commented 4 years ago

What do we think of this form?


type BinaryOperator<T> = (x: T, y: T) => T

class Foo {
    // Notice the lack of "="
    sum: BinaryOperator<number> (x, y) {
      return x+y;
    }
}

This would be a nice parallel to usual variable type declaration. I feel like the as X expression is an assertion instead of a declaration. Like, if you were to use it on an arrow function:


const sum = ((x,y,z) => false) as BinaryOperator<number> // sum is (number,number) => number

const sum: BinaryOperator<number> = ((x,y,z) => false) //error!

I do like the idea of declaring the typing for methods though.

bodinsamuel commented 3 years ago

+1 on this It would be very useful

class Foo {
    // Notice the lack of "="
    sum: BinaryOperator<number> (x, y) {
      return x+y;
    }
}

This solution feels good to me πŸ‘πŸ»


Note that I would also expect to work with (or as an alternative) implements

interface IFoo {
  sum: BinaryOperator<number>
}

class Foo implements IFoo {
  sum() (x, y) {
      return x+y;
    }
}