invokeWith

invokeWith

  • (args: any[]) => (fn: function) => Result
  1. Call fn with args and return the result.

    const greetMark = greeting => {
      console.log(greeting + ' Mark')
    }
    
    const invokeWithOhHi = invokeWith(['Oh hi'])
    
    invokeWithOhHi(greetMark)
    // prints 'Oh hi Mark'
    const greetMark = (greeting: string) => {
      console.log(greeting + ' Mark')
    }
    
    const invokeWithOhHi = invokeWith(['Oh hi'])
    
    invokeWithOhHi(greetMark)
    // prints 'Oh hi Mark'
    
    const greetMark = greeting => {
      console.log(greeting + ' Mark')
    }
    
    const invokeWithOhHi = invokeWith(['Oh hi'])
    
    invokeWithOhHi(greetMark)
    // prints 'Oh hi Mark'
    const greetMark = (greeting: string) => {
      console.log(greeting + ' Mark')
    }
    
    const invokeWithOhHi = invokeWith(['Oh hi'])
    
    invokeWithOhHi(greetMark)
    // prints 'Oh hi Mark'
    
  2. Occasionally we'll encounter a design pattern where a collection of functions takes the same arguments. Below, we're developing a screen to be shown across the Nebraska Zoo. Each data accessor takes the animal's name to get its value. Let's invoke each accessor with the name of the animal and get all their data.

    const animalDirectory = {
      Marty: 'Zebra',
      Perry: 'Platypus',
      Rosie: 'Flamingo',
    }
    const mammalDb = new Set(['Zebra', 'Platypus'])
    const animalHeights = {
      Marty: `4'2"`,
      Perry: `1'10"`,
      Rosie: `3'9"`,
    }
    
    const accessors = {
      animal: name => animalDirectory[name],
      isMammal: name => {
        const animal = animalDirectory[name]
        return mammalDb.has(animal)
      },
      height: name => animalHeights[name],
    }
    
    const getDataFor = name => {
      const invokeWithName = invokeWith(name)
      const getDataForName = mapValues(invokeWithName)
      return getDataForName(accessors)
    }
    
    const rosieData = getDataFor('Rosie')
    console.log(rosieData)
    // is {
    //   animal: Flamingo,
    //   isMammal: false,
    //   height: 3'9"
    // }
    type Name = keyof typeof animalDirectory
    const animalDirectory = {
      Marty: 'Zebra',
      Perry: 'Platypus',
      Rosie: 'Flamingo',
    }
    const mammalDb = new Set(['Zebra', 'Platypus'])
    const animalHeights = {
      Marty: `4'2"`,
      Perry: `1'10"`,
      Rosie: `3'9"`,
    }
    
    type Accessors = typeof accessors
    const accessors = {
      animal: (name: Name) => animalDirectory[name],
      isMammal: (name: Name) => {
        const animal = animalDirectory[name]
        return mammalDb.has(animal)
      },
      height: (name: Name) => animalHeights[name],
    }
    
    type AccessorKeys = keyof Accessors
    type Data = {
      [K in AccessorKeys]: ReturnType<Accessors[K]>
    }
    const getDataFor = (name: Name): Data => {
      const invokeWithName = invokeWith([name] as const)
      const getDataForName = mapValues(invokeWithName<string | boolean>)<Accessors>
      return getDataForName(accessors) as Data
    }
    
    const rosieData = getDataFor('Rosie')
    console.log(rosieData)
    // is {
    //   animal: Flamingo,
    //   isMammal: false,
    //   height: 3'9"
    // }
    
    const animalDirectory = {
      Marty: 'Zebra',
      Perry: 'Platypus',
      Rosie: 'Flamingo',
    }
    const mammalDb = new Set(['Zebra', 'Platypus'])
    const animalHeights = {
      Marty: `4'2"`,
      Perry: `1'10"`,
      Rosie: `3'9"`,
    }
    
    const accessors = {
      animal: name => animalDirectory[name],
      isMammal: name => {
        const animal = animalDirectory[name]
        return mammalDb.has(animal)
      },
      height: name => animalHeights[name],
    }
    
    const getDataFor = name => {
      const invokeWithName = invokeWith(name)
      const getDataForName = mapValues(invokeWithName)
      return getDataForName(accessors)
    }
    
    const rosieData = getDataFor('Rosie')
    console.log(rosieData)
    // is {
    //   animal: Flamingo,
    //   isMammal: false,
    //   height: 3'9"
    // }
    type Name = keyof typeof animalDirectory
    const animalDirectory = {
      Marty: 'Zebra',
      Perry: 'Platypus',
      Rosie: 'Flamingo',
    }
    const mammalDb = new Set(['Zebra', 'Platypus'])
    const animalHeights = {
      Marty: `4'2"`,
      Perry: `1'10"`,
      Rosie: `3'9"`,
    }
    
    type Accessors = typeof accessors
    const accessors = {
      animal: (name: Name) => animalDirectory[name],
      isMammal: (name: Name) => {
        const animal = animalDirectory[name]
        return mammalDb.has(animal)
      },
      height: (name: Name) => animalHeights[name],
    }
    
    type AccessorKeys = keyof Accessors
    type Data = {
      [K in AccessorKeys]: ReturnType<Accessors[K]>
    }
    const getDataFor = (name: Name): Data => {
      const invokeWithName = invokeWith([
        name,
      ] as const)
      const getDataForName = mapValues(
        invokeWithName<string | boolean>
      )<Accessors>
      return getDataForName(accessors) as Data
    }
    
    const rosieData = getDataFor('Rosie')
    console.log(rosieData)
    // is {
    //   animal: Flamingo,
    //   isMammal: false,
    //   height: 3'9"
    // }