Type annotation for `this` keyword in Typescript

后端 未结 1 1785
挽巷
挽巷 2020-12-07 01:31

I have a standalone function that\'s meant to use the context provided by Function.prototype.call.

For example:

function foo () {
    re         


        
相关标签:
1条回答
  • 2020-12-07 02:03

    It's a bit ugly, in my opinion.

    First of all, you can use the special this parameter syntax to identify the type of object you expect this to be:

    function foo (this: {bar: string}) {
        return this.bar; // no more error
    }
    

    which helps if you call it directly:

    foo(); // error, this is undefined, not {bar: string}
    
    var barHaver = { bar: "hello", doFoo: foo };
    barHaver.doFoo(); // acceptable, since barHaver.bar is a string
    
    var carHaver = { car: "hello", doFoo: foo };
    carHaver.doFoo(); // unacceptable, carHaver.bar is undefined
    

    But you want to use foo.call(). Unfortunately the Function.prototype.call() typing in TypeScript won't really enforce this restriction for you:

    foo.call({ bar: "baz" }); // okay, but
    foo.call({ baz: "quux" }); // no error, too bad!
    

    Merging something better into TypeScript's Function declaration caused me problems, (First point of ugliness; you will need to cast foo to something) so you can try something like this:

    interface ThisFunction<T extends {} = {}, R extends any = any, A extends any = any> {
      (this: T, ...args: A[]): R;
      call(thisArg: T, ...args: A[]): R;
    }
    

    A ThisFunction<T,R,A> is a function with a this of type T, a return value of type R, and a rest argument of type A[]. (Second point of ugliness: you can't easily specify multiple arguments of different types in a way that will be enforced by the type system.)

    You can then cast foo to ThisFunction<{ bar: string }, string>, (Third point of ugliness: the type system just will not infer this types) and then finally use call():

    (<ThisFunction<{ bar: string }, string>>foo).call({ bar: "baz" }); // okay, and
    (<ThisFunction<{ bar: string }, string>>foo).call({ baz: "quux" }); // error, hooray!
    

    Hope that helps!

    0 讨论(0)
提交回复
热议问题