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 parmater with union type not working as expected (not assignable to parameter of type) #57299

Closed
JasonMan34 opened this issue Feb 5, 2024 · 2 comments

Comments

@JasonMan34
Copy link

JasonMan34 commented Feb 5, 2024

πŸ”Ž Search Terms

union, generic, assignable, not assignable to parameter of type

πŸ•— Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about union and generics

⏯ Playground Link

https://www.typescriptlang.org/play?#code/MYewdgzgLgBFCGBrApgZSgJwJZgOYwF4YAKAB3g3gFsAuGabPASkID4YBXMAE2QDMcybgG4AUKEiwEKAHIcqAI2QZCJcpVoww8pRhYF2XXgLBCxoqAE9SyGADEuwVVZsg+cJGkw58AHzjWyG4esjrK5hLQMFTICA5gTkQAPAAqMMgAHlDIPBD2jqzEfI50KQA0MOrUdAAKFNSxyhCprADaAAwAuvrsAN6iMDAA9EMwAIIYuPI5sMEutgDkDD4w-tqKygswWHlgILDwEBBYuGDwCgA2tlAglfUx2SpzgTALpgBumwB0A8OjKS8lt48Fsdlp9jBDsdTucrnBbvNXh9Nr9igkyPcmGIAL6iUQjGAAmzbMB8ZQ5YC2ADuIAwiDyh3SGRswGy3BgVIAFjkYMB4BcLisoNyYGjWVhwPjRhMpjEwLN3Ii3mEMKDdhCoSczpdrrcqg9lDBnsSgYxcAtRA94PFgMRpF4zRUAExMURAA

πŸ’» Code

const takeString = (param: string) => undefined;
const takeNumber = (param: number) => undefined;

type Func = typeof takeString | typeof takeNumber;

const metaFunc = <T extends Func>(func: T, param: Parameters<T>[0]) => {
  // Argument of type 'string | number' is not assignable to parameter of type 'never'.
  // Type 'string' is not assignable to type 'never'
  func(param);
}

// Type inference works as expected when calling the function
// Argument of type 'number' is not assignable to parameter of type 'string'
metaFunc(takeString, 2)

πŸ™ Actual behavior

The func invocation is invalid. With the error:

Argument of type 'string | number' is not assignable to parameter of type 'never'.
  Type 'string' is not assignable to type 'never'

πŸ™‚ Expected behavior

TypeScript should recognize that since the same T is used for both func and param, the invocation of func(param) is valid. Similar to how it recognizes that metaFunc(takeString, XXX) should be called with a string rather than a string | number

Additional information about the issue

Potentially related: #51587, #33912, #30581

Note that this is different than https://github.com/microsoft/TypeScript/issues/30581#issuecomment-476417974 since the same T extends Func is used for both func and param, rather than using Func for both types

@snarbies
Copy link

snarbies commented Feb 5, 2024

As defined, this is a valid invocation of metaFunc

metaFunc<Func>(takeString, 3);

// Maybe something you'd be more likely to see in the wild
const myFunc = ((arg: string) => undefined) as Func;
metaFunc(myFunc, 3);

It might not be practical in your actual use case but in your example, this workaround is available:

const metaFunc = <T extends string | number>(func: (arg: T)=>undefined, param: T) => {
    // ...
}

@JasonMan34
Copy link
Author

I see the issue.
The workaround actually works great for me:

type Func<T extends string | number> = (arg: T) => undefined

const metaFunc = <T extends string | number>(func: Func<T>, param: T) => {
  func(param);
}

Of course in real life Func is more complicated, but as long as I can neatly wrap it in it's own type it doesn't bother me

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants