Closed as not planned
Description
π Search Terms
never, intersection, contradiction
π Version & Regression Information
- This is the behavior in every version I tried, and I reviewed the FAQ for entries about
never
β― Playground Link
π» Code
// These variations on never are both reported by intellisense as `never`.
// That's a problem because they behave differently in a subtle way
type NominalNever = never
// ^?
type StructuralNever = {x:1} & {x:2}
// ^?
// We will be exploring this with the builtin ReturnType generic type
// type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any;
// ReturnType constrains the generic so non-callable types give a useful error message
// @ts-expect-error
type R0 = ReturnType<{x:1}> // error - very helpful!
// `never` is treated specially by the conditional type construct
// the conditional is short-circuited and the conditional evaluates to `never` instead of either the true or false branch.
type R1 = ReturnType<never> // never
// ^?
// but with an impossible intersection,
// 1. the type constraint does not kick in as a safeguard
// 2. the conditional is not short-circuited to 'never'
// 3. the conditional evaluates to the true branch only even though there's no reason to prefer either branch
// the return type is inferred as `unknown`, seemingly because it's an upper bound on the type parameter
// type R2 = unknown; expected never
type R2 = ReturnType<{x:1} & {x:2}>
// ^?
// even if a return type is *structurally* declared, it is ignored by type inference
// type R3 = unknown; expected "X"
type R3 = ReturnType<{x:1} & {x:2} & ((...args: any[]) => "X")>
// ^?
π Actual behavior
When intersecting two object types with a conflicting value, the user-observable hinted type is never
, but the type interacts with generic templates in a nonsensical way.
π Expected behavior
I expect either (or both):
- conflicting intersections to treated the same as the nominal
never
type for constrained generics and conditional types. In particular:- The generic constraint would need to be (re)checked, so that an error is reported if the type constraint is refuted.
- The conditional type will need to be (re)checked, so that the conditional is
never
- conflicting intersections to be represented by their structural properties instead of an opaque "
never
" type.- This might be nice to do anyway. Such
never
s merit different compiler behavior (e.g. when trying to access a property on a conflicted type) so showing it as e.g.never<"conflicted .x">
would go a long way to making the behavior less frustratingly opaque.
- This might be nice to do anyway. Such
Additional information about the issue
No response