1

Lets say i have this generic function:

const myFn = <T>(p: {
  a: (n: number) => T,
  b: (o: T) => void,
}) => {
  // ...
}

If i use myFn with no parameter for function a it works and the type of T can be inferred from the return type of a:

myFn({
  a: () => ({ n: 0 }), // Parameter of a is ignored
  b: o => { o.n }, // Works!
})

but if i want to use the parameter for function a suddenly the type of T can not be inferred:

myFn({
  a: i => ({ n: 0 }), // Parameter i is used
  b: o => { o.n }, // Error at o: Object is of type 'unknown'.ts(2571)
})

Can someone explain this behavior? How can i fix this such that the type of T can be inferred from the return type of a?

Quesstor
  • 262
  • 2
  • 8
  • 2
    This looks like an issue of Typscript which is unable to infer the T correct type (inferring as `unknown` in case of having parameter). I think you can work around this issue until it gets fixed by using high order function technique `myFn = (a: (...arg: any[]) => T) => (b: (o: T) => void) {}`. It should work then. – tmhao2005 Jan 02 '21 at 16:55
  • Strange, it also works if you specify `i`'s type explicitly https://www.typescriptlang.org/play?jsx=0#code/MYewdgzgLgBAtgTwGJhgXhgHgCoD4AUADgFwwDeAUDDAIan5ilgCucARgKYBOAlOrjGwAaKjDb0QpbHzQCAbiACWAExEBfGQMrUA9DpgA6IxTUUKiFPm216mmFZiMYABhgahMPTAAKNLjTgOKG4YEAAzWhhFCCiAczAQLg5lUXFQ-nJQg1Q1Dy8AdUSAawgAQhMeMwswK1E6e0UmVk5eDIcnV3dPfV9-QOCuKKiY5ghk1NIQDLIsnPUeIA – Aleksey L. Jan 03 '21 at 13:08

1 Answers1

1

AFTER TypeScript 4.7

Just switch to TypeScript 4.7, see this

BEFORE TS 4.7

Extra generic for b should help:

const myFn = <T,>(p: {
  a: (n: number) => T,
  b: <U extends T /* EXTRA U generic */>(o: U) => void,
}) => {
  // ...
}


myFn({
  a: () => ({ n: 0 }), // Parameter of a is ignored
  b: o => { o.n }, // Works!
})

myFn({
  a: i => ({ n: 0 }), // Parameter i is used
  b: o => { o.n }, // Works 
})

This article should help to understand why your approach did not work