Skip to content

Generic string union argument on function not compatible with conditional type in inner function argument #43147

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
ranneyd opened this issue Mar 8, 2021 · 2 comments
Labels
Duplicate An existing issue was already created

Comments

@ranneyd
Copy link

ranneyd commented Mar 8, 2021

Bug Report

πŸ”Ž Search Terms

conditional, generic, inference, assertion, union

πŸ•— Version & Regression Information

I'm using 4.2.3. I haven't tried it in other versions, but I have no reason to believe this ever worked.

⏯ Playground Link

Playground link with relevant code

πŸ’» Code

type Foo = { val: string };
type Bar = { val: number };

const func = <T extends "foo" | "bar">(key: T) =>
  (funcArg: (input: T extends "foo" ? Foo : Bar) => void) => {
    funcArg((key === "foo" ? { val: "test"} : { val: 123 }) as T extends "foo" ? Foo : Bar);
    // funcArg(key === "foo" ? { val: "test"} : { val: 123 });
  }

πŸ™ Actual behavior

Suppose I have two disjoint types Foo and Bar. I make a function that takes a key that's either foo or bar. This function returns a function that takes a function called funcArg. When key is foo, funcArg takes a Foo, and when key is bar, it takes a Bar.

In my inner function body, I call funcArg. I check what key is, and pass an appropriate value. Doing so gives me this:

Argument of type '{ val: string; } | { val: number; }' is not assignable to parameter of type 'T extends "foo" ? Foo : Bar'.
  Type '{ val: string; }' is not assignable to type 'T extends "foo" ? Foo : Bar'.(2345)

I have to add as T extends "foo" ? Foo : Bar to the argument when I call funcArg.

πŸ™‚ Expected behavior

Since T is a union type, I expect TypeScript to follow the branches. When T is "foo", then funcArg will take type Foo. The key === "foo" conditional will produce a Foo. TypeScript is treating key as foo or bar all the way down into the inner function definition, when really it's already decided by that point, since key has to be one or the other.

It's like a quantum-mechanics/SchrΓΆdinger's-cat situation where key can be either "foo" or "bar" until it's "observed" at runtime. But were that so, then how does the conditional type on funcArg work? How do conditional types work at all? Also, TypeScript seems to do just fine with conditionals/ternaries at runtime, having no issues with things like typeof val === "function" ? val() : val.

@RyanCavanaugh
Copy link
Member

See #33912

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Mar 8, 2021
@typescript-bot
Copy link
Collaborator

This issue has been marked as a 'Duplicate' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Duplicate An existing issue was already created
Projects
None yet
Development

No branches or pull requests

3 participants