Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generic type inference prefers conditional types #31766

Closed
bowenni opened this issue Jun 4, 2019 · 5 comments · Fixed by #32208
Closed

Generic type inference prefers conditional types #31766

bowenni opened this issue Jun 4, 2019 · 5 comments · Fixed by #32208
Assignees
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue

Comments

@bowenni
Copy link

bowenni commented Jun 4, 2019

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

@RyanCavanaugh
Copy link
Member

What is the intent of writing T extends any ?

@RyanCavanaugh RyanCavanaugh added the Needs More Info The issue still hasn't been fully clarified label Jun 13, 2019
@bowenni
Copy link
Author

bowenni commented Jun 13, 2019

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 removed the Needs More Info The issue still hasn't been fully clarified label Jun 13, 2019
@RyanCavanaugh
Copy link
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'.
}

@RyanCavanaugh RyanCavanaugh added the Bug A bug in TypeScript label Jun 25, 2019
@RyanCavanaugh RyanCavanaugh added this to the TypeScript 3.6.0 milestone Jun 25, 2019
@ahejlsberg
Copy link
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
Copy link
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

@ahejlsberg ahejlsberg added the Fixed A PR has been merged for this issue label Jul 2, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript Fixed A PR has been merged for this issue
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants