Repository navigation
unknown[] as rest params with generic parameter breaks generic inference #27439
Description
Activity
DanielRosenwasser commented
on Sep 28, 2018 MemberMore actionsThis is due to two things:
Thas an implicit constraint of{}which is a subtype ofunknown.- Since parameters are contravariantly related,
unknown[]is a problematic type forargsinReturnOf. This is becauseunknownisn't assignable to{}(remember, contravariance means we switch directions when relating two types).
You'd be best off picking the lowest bound for the type of
argsby usingnever:type ReturnOf<F> = F extends (...args: never[]) => infer U ? U : never;
If #26796 were solved, this would've worked, but I still believe
neveris the best type here.- addedWorking as IntendedThe behavior described is the intended behavior; this is not a bugThe behavior described is the intended behavior; this is not a bug
on Sep 28, 2018 jack-williams commented
on Sep 28, 2018 CollaboratorMore actionsEDIT: Sorry I have successfully managed to confuse myself, feel free to ignore my question.
Daniel Rosenwasser (@DanielRosenwasser) So functions are contravariant in the the domain when checking conditional types, even with strictFunctionTypes off?
// --strictFunctionTypes: off declare function f<T>(x: T): T; type ReturnOf<F> = F extends (...args: unknown[]) => infer U ? U : never; type Test<F> = F extends (...args: unknown[]) => unknown ? unknown : never; declare const d: ReturnOf<typeof f>; // never; declare const e: Test<typeof f>; // unknown;
What I think is happening is that first
Uis inferred from the base constraint ofT, so is{}, it then tries to unify<T>(x: T): Tand the inferred type(...args: unknown[]) => {}, which actually instantiatesTto beunknownby using the domain, so you get an error on the return type. I think this is why the behavior is independent of strict function checks.- removedWorking as IntendedThe behavior described is the intended behavior; this is not a bugThe behavior described is the intended behavior; this is not a bug
on Sep 29, 2018 DanielRosenwasser commented
on Sep 29, 2018 MemberMore actionsHmm, I want to say you're right, but I'd like to check with Anders Hejlsberg (@ahejlsberg) or Wesley Wigham (@weswigham) first.
Reacted by Jack WilliamsJack Williams (@jack-williams) Daniel Rosenwasser (@DanielRosenwasser) That is indeed what is happening.
- addedDesign LimitationConstraints of the existing architecture prevent this from being fixedConstraints of the existing architecture prevent this from being fixed
on Oct 1, 2018
TypeScript Version: 3.1.0
Search Terms: unknown conditional rest params
Code
Expected behavior:
dis the same asc(i.e. type{})Actual behavior:
dis typeneverPlayground Link
Related Issues: didn't see any; apologies if I missed it
Notes: this only happens if there's a
T-typed (or union withT) parameter. Even something likePromise<T>seems to cause it to evaluate to{}. I'm not even 100% sure this is a bug (I might be missing/misunderstanding something in howunknownis handled), but it seems like in this situation it should behave the same as theanyversion.