Skip to content

Conditional types do not work in generic functions #53455

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

Closed
ns-vpanfilov opened this issue Mar 23, 2023 · 2 comments
Closed

Conditional types do not work in generic functions #53455

ns-vpanfilov opened this issue Mar 23, 2023 · 2 comments
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed

Comments

@ns-vpanfilov
Copy link

Bug Report

I've created a type that converts all undefined properties to optional. This types works well, however fails when used in generic functions:

type UndefinedKeys<T> = { [P in keyof T]: undefined extends T[P] ? P : never }[keyof T]
type OptionalUndefined<T> = Partial<Pick<T, UndefinedKeys<T>>> & Omit<T, UndefinedKeys<T>>

🔎 Search Terms

generic function

🕗 Version & Regression Information

This is the behavior in every version I tried ( 5.0.2 and 4.9.5 )

⏯ Playground Link

Playground link with relevant code

💻 Code

type UndefinedKeys<T> = { [P in keyof T]: undefined extends T[P] ? P : never }[keyof T]
type OptionalUndefined<T> = Partial<Pick<T, UndefinedKeys<T>>> & Omit<T, UndefinedKeys<T>>

type TSample<
  U extends Record<string, any> | undefined,
  D extends Record<string, any>
> = { undef: U, def: D }


function fn<
  U extends Record<string, any> | undefined,
  D extends Record<string, any>
>(params: OptionalUndefined<TSample<U, D>>) {
  {
    // ERROR: both properties do not exist on type 'OptionalUndefined<TSample<U, D>>'
    const { def, undef } = params
  }

  {
  // works as expected
  const { def, undef } = params as OptionalUndefined<
      TSample<
        Record<string, any> | undefined,
        Record<string, any>
      >
    > 
  }
}

🙁 Actual behavior

typescript cannot properly determine parameter type

🙂 Expected behavior

I expect typescript to use definition of U (extends Record<string, any> | undefined) and D (``) to be used to determine the type of parameters and params should have `{ undef?: Record<string, any> | undefined, def: Record<string, any> }` type?

Notice how, when I explicitly specify the type of params, it works properly.

@MartinJohns
Copy link
Contributor

Resolving of conditional types including unbound type arguments is deferred. This is a design limitation.

TypeScript can't resolve your conditional type within the function because it doesn't know what types U and D are.

@fatcerberus
Copy link

fatcerberus commented Mar 23, 2023

Conveniently, this issue makes a good case against #53452. Partial by itself currently works in generic contexts.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Design Limitation Constraints of the existing architecture prevent this from being fixed
Projects
None yet
Development

No branches or pull requests

4 participants