Search code examples
javascripttypescriptsyntaxcallbackes6-promise

Typescript coding styling with then method accepting a declared function


I am struggling with typeScript syntax used in the snippet below. Can someone kindly clear it out for me.

type Reply = (reply: Replies.AssertExchange) => string

const announce: (text: string) => Reply = (text: string): Reply => {
  return (reply: Replies.AssertExchange): string => {
    return `${text} ${(reply as Replies.AssertExchange).exchange}`
  }
}

channel.assertExchange('someName', 'fanout').then(announce('Exchange assertion'))

Here the return type of method channel.assertExchange() is promise i.e Promise<Replies.AssertExchange>

The style that is confusing me is, normally the .then() function should take the returned object i.e Replies.AssertExchange or a function working on the return object without arguments. However, here it's taking a function with string argument i.e announce('Exchange assertion').

would be nice if an example is presented in a normal .then() form.


Solution

  • The style that is confusing me is, normally the .then() function should take the returned object i.e Replies.AssertExchange or a function working on the return object without arguments. However, here it's taking a function with string argument i.e announce('Exchange assertion').

    announce is a double arrow function. It is a function which returns a function (also known as "currying").

    These two statements are the same:

    .then(announce('Exchange assertion'))
    
    .then(reply => announce('Exchange assertion')(reply))
    

    Using a curried function means that you can avoid having to write out the reply => part. The value of announce('Exchange assertion') is exactly what you think it should be -- a function that takes a Replies.AssertExchange as its argument.

    I agree that the announce function is written in a very confusion way. This line in particular is convoluted:

    const announce: (text: string) => Reply = (text: string): Reply => {
    

    The first : (text: string) => Reply gives the type of the variable announce. It is a function that takes a string and returns a Reply.

    The second = (text: string): Reply => is the implementation.

    This sort of duplicated typing is not necessary. We can just provide types for the implementation and typescript will be able to figure out the type for the variable announce based on that.

    Perhaps this makes it a bit clearer:

    const announce = (text: string) => 
      (reply: Replies.AssertExchange): string => 
        `${text} ${reply.exchange}`;
    

    When you call announce with a text: string, you get a function (reply: Replies.AssertExchange): string.

    So the type of announce('Exchange assertion') is (reply: Replies.AssertExchange): string.