Search code examples
typescript

Object is of type 'unknown' typescript generics


I have a simple function that takes a function as it's argument and returns a new function. I get Object is of type 'unknown' when calling the returned function

const makeFunction = <T>(callback: (someParam: number, options: T) => any) => {

  return (options: T) => {
    const param = 4;

    return callback(param, options)  
  }  
}

Above code is okay for typescript but when I am calling function I get complaint

makeFunction((param, options) => {
  const a = options.optionsValue //(parameter) options: unknown,  Object is of type 'unknown'
})({optionsValue: 'some value'})

Solution

  • We need to think how TS can infer the type from this definition. TS can understand type from two places:

    • explicit generic type set
    • type of second argument of the function

    In your use case you don't provide type in any of those places and this is the reason you get unknown, because how TS can know what argument type you need. In order to give TS possibility to understand the type you can do or:

    Set explicitly generic by:

    makeFunction<YourType>((param, options) => {...))
    

    Set type in callback function by for example defining one beforehand:

    const f = (a: number, b: {a: string}) => b // here types are set
    makeFunction(f)({a: 'some value'}) // makeFunction is able to infer the types by f
    

    You can also do this inline by saying ((param: number, options: MyType))

    Answer after comment if options can be dynamic

    I believe you want below behavior:

    const makeFunction = <F extends (someParam: number, options: any) => any>(callback: F) => {
    
      return (options: Parameters<F>[1]) => {
        const param = 4;
    
        return callback(param, options)  
      }  
    }
    const f = (a: number, b: {a: string}) => b
    makeFunction(f)({ a: 'a' })
    const g = (a: number, b: {b: number}) => b
    makeFunction(g)({b: 1})
    

    We say few things:

    • F is now function which extends from binary function, and we directly infer its type
    • Parameters<F>[1] is second argument type of given function F type