After spending almost two days in finding the issue, I ran across a few
TypeScript issues on their GitHub page:
- Loss of type inference converting to named parameters object
https://github.com/Microsoft/TypeScript/issues/29791
- Parameter of a callback without a specified type next to it breaks code.
https://github.com/Microsoft/TypeScript/issues/29799
- Convert to named parameters
https://github.com/Microsoft/TypeScript/pull/30089
It became clear that TypeScript is unable to infer method return
arguments if a generic type is used more than once in generic parameter
object. Instead it returns {}.
For example, the following would fail on line 28:
type Convert<A, B> = (value: A) => B
interface IParams<C, D> {
value: C
convert: Convert<C, D>
doConvert: (value: C, convert: this['convert']) => D
}
function doSomething<E, F>(value: E, convert: Convert<E, F>) {
return convert(value)
}
function build<G, H>(params: IParams<G, H>) {
const {value, convert} = params
return params.doConvert(value, convert)
}
const outerResult = build({
value: {
a: {
value: 1,
},
b: 'string',
},
convert: value => value.a,
doConvert: (value, convert) => {
const innerResult = doSomething(value, convert)
innerResult.value
console.log('innerResult:', innerResult)
return innerResult
},
})
console.log('outerResult:', outerResult)
With the message:
Property 'value' does not exist on type '{}'.
If we replace parameter object IParams with regular ordered function
parameters, the compilation succeeds.
RyanCavanough (TS project lead) from GitHub commented:
> We don't have a separate pass to say "Go dive into the function and
> check to see if all its return statements don't rely on its parameter
> type" - doing so would be expensive in light of the fact that extremely
> few real-world functions actually behave like that in practice.
Source: https://github.com/Microsoft/TypeScript/issues/29799#issuecomment-464154659
These modifications bring type safety to TestUtils.tsx, and therefore
client-side tests of React components, while keeping almost the same
ease of use as before.