Skip to content

Generic type inference prefers conditional types #31766

Closed
@bowenni

Description

@bowenni

TypeScript Version: 3.4.5 and 3.5.1

Search Terms: Conditional types, Type inference

Code

interface I {a: string}
type Cond<T> = T extends any ? Partial<T>: T;

declare function f<T>(x1: T, x2: Cond<T>): T;
function g(p1: I, p2: Cond<I>): I {
  return f(p1, p2); // error here
}

Expected behavior:
No errors. A trivial type inference is T=I. This is also the behavior of TypeScript 3.3.

Actual behavior:
error TS2322: Type 'Partial<I>' is not assignable to type 'I'.
From that error message the actual inference is T=Partial<I> (or Cond<I>), which seems like a regression to me.

Playground Link:
playground link

Related Issues:
There are some issues around conditional types but nothing quite a duplication, I think.
#31601 requires function overloads
#24085 is a problem with enums
#30489 is more about type inference on the conditional type itself, not the generic type when the conditional type is used
#30341 is similar but it's marked as fixed

@rkirov

Activity

RyanCavanaugh

RyanCavanaugh commented on Jun 13, 2019

@RyanCavanaugh
Member

What is the intent of writing T extends any ?

bowenni

bowenni commented on Jun 13, 2019

@bowenni
Author

What is the intent of writing T extends any ?

To create a conditional type. I think the problem only happens with a conditional type.

If the example is oversimplified and doesn't make sense, below is another example, without the T extends any.

interface I { a: string }
type DeepPartial<T> =
    T extends object ? {[K in keyof T]?: DeepPartial<T[K]>} : T;

declare function f<T>(t: T, partial: DeepPartial<T>): T;
function g(p1: I, p2: Partial<I>): I {
  return f(p1, p2); // error Type 'Partial<I>' is not assignable to type 'I'.
}
RyanCavanaugh

RyanCavanaugh commented on Jun 25, 2019

@RyanCavanaugh
Member
interface I { a: string }
type DeepPartial<T> =
    T extends object ? {[K in keyof T]?: DeepPartial<T[K]>} : T;

declare function f<T>(t: T, partial: DeepPartial<T>): T;
function g(p1: I, p2: Partial<I>): I {
    // T inferred to be Partial<I>; should be I
  return f(p1, p2); // error Type 'Partial<I>' is not assignable to type 'I'.
}
ahejlsberg

ahejlsberg commented on Jul 1, 2019

@ahejlsberg
Member

This is caused by #30010. Part of why we inferred to a union type was to get lower priority candidates for inferences to naked type variables, but that got lost with the fix in #30010. We just need to reinstate that part.

weswigham

weswigham commented on Jul 2, 2019

@weswigham
Member

This is caused by #30010.

To be fair, at the time I'm pretty sure we had done away with the naked type variable priority; we just didn't think to add it to the conditional inference bit when we added it back. :P

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

BugA bug in TypeScriptFixedA PR has been merged for this issue

Type

No type

Projects

No projects

Relationships

None yet

    Development

    Participants

    @bowenni@weswigham@ahejlsberg@RyanCavanaugh

    Issue actions

      Generic type inference prefers conditional types · Issue #31766 · microsoft/TypeScript