`ReturnType` and `InstanceType` don't work for functions/constructors with `never` in their parameters
Opened this issue ยท 3 comments
๐ Search Terms
ReturnType InstanceType any never
๐ Version & Regression Information
- This is the behavior in every version I tried, and I reviewed the FAQ for entries about
ReturnTypeandInstanceType.
โฏ Playground Link
๐ป Code
type _1 = ReturnType<(...args: never) => 'foo'>
// ^? type _1 = any
type _2 = InstanceType<new (...args: never) => 'foo'>
// ^? type _2 = any๐ Actual behavior
ReturnType and InstanceType always evaluate to any when given a function/constructor whose parameters are ...args: never (or ...args: never[], a: never, b: string, etc).
๐ Expected behavior
ReturnType and InstanceType should return the actual return/instance type.
Additional information about the issue
Changing the parameter constraint in the conditions of these types from any to never seems to fix the issue:
type ReturnType<T extends (...args: any) => any> = T extends (...args: never) => infer R ? R : any
type InstanceType<T extends abstract new (...args: any) => any> = T extends abstract new (...args: never) => infer R ? R : anyI don't think this will cause any regressions, and did some spot-checking to validate that, but haven't run the entire test suite or anything like that yet.
If someone wants to put up a PR for the suggested lib file change, we can run the battery of test suites against it and see if any breaks turn up in the wild.
Given that (...args: Array<never>) => unknown does not work with the built-in ReturnType<F> utility type, I have to assume there is a different intended way of representing the type of "all possible functions." How would one do so without using any, which is unsafe?
I assumed the same as OP, based on the rules for function subtyping. Flow also uses (...$ReadOnlyArray<empty>) => mixed, which is their equivalent (modulo the ReadonlyArray).
However, I have been unable to find anything through experimentation, and the Functions documentation doesn't mention this at all.
I have to assume there is a different intended way of representing the type of "all possible functions."
I think this is just a bug/oversight, not signalling that (...args: never) => unknown1 is intended to be avoided. The pull request which would close this issue is in limbo, but never-typed parameters "should" be acceptable.
If you want a pragmatic answer to "what do I do in the meantime?": it depends, but you could use any in parameters in situations where there's no callable value anyway (in that case it's safe), or use never and avoid applying the built-in ReturnType & InstanceType utility types in these cases. I typically do the latter and just inline an infer when I need to extract a return type.