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

Can't use boolean as parameter for a function with overrides for parameter of type true and false #44967

Closed
golergka opened this issue Jul 10, 2021 · 3 comments
Labels
Duplicate An existing issue was already created

Comments

@golergka
Copy link

Bug Report

🔎 Search Terms

Function overloading, sum types, function parameters, type inferrence

🕗 Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about function overloading and type inferrence

⏯ Playground Link

Playground link with relevant code

💻 Code

function test(input: true): "true"
function test(input: false): "false"
function test(input: boolean): "true"|"false" {
  return input.toString() as "true"|"false"
}

function test2(): boolean {
  throw new Error("not implemented")
}

const a: boolean = test2()
test(a)

🙁 Actual behavior

No overload matches this call.
  Overload 1 of 2, '(input: true): "true"', gave the following error.
    Argument of type 'boolean' is not assignable to parameter of type 'true'.
  Overload 2 of 2, '(input: false): "false"', gave the following error.
    Argument of type 'boolean' is not assignable to parameter of type 'false'.

🙂 Expected behavior

Code compiles, test(a) result is inferred to be "true"|"false".

@golergka
Copy link
Author

Here's a more realistic example where this feature could actually made my code more correct and easy to read. I have something akin to following:

function f1(input: 'a' | 'b'): 'c' | 'd' {
  throw new Error('not implemented')
}

function f2(input: 'c' | 'd'): 'e' | 'f' {
  throw new Error('not implemented')
}

function f3(input: 'e' | 'f'): 'g' | 'h' {
  throw new Error('not implemented')
}

function f0(): 'a' | 'b' {
  throw new Error('not implemented')
}

const ab = f0()
const cd = f1(ab)
const ef = f2(cd)
const gh = f3(ef)

(In the real code those types aren't constants but tagged unions). This code is correct, but here the types of ab, cd, ef and gh can exist in any combinations. So, if I try to use those values, I'll have to write either checks or casts for all those variables to determine what variant do they belong to.

However, I know that in my real code, f1 always returns c for input of a and d for input of b, and so do all the following functions. Which means that in reality, it would have been enough to write only one check — and I would know the types of all of them. Trying to explain this fact to the type system, I write function overloads.

function f1(input: 'a'): 'c'
function f1(input: 'b'): 'd'
function f1(input: 'a' | 'b'): 'c' | 'd' {
  throw new Error('not implemented')
}

function f2(input: 'c'): 'e'
function f2(input: 'd'): 'f'
function f2(input: 'c' | 'd'): 'e' | 'f' {
  throw new Error('not implemented')
}

function f3(input: 'e'): 'g'
function f3(input: 'f'): 'h'
function f3(input: 'e' | 'f'): 'g' | 'h' {
  throw new Error('not implemented')
}

function f0(): 'a' | 'b' {
  throw new Error('not implemented')
}

const ab = f0()
const cd = f1(ab)
const ef = f2(cd)
const gh = f3(ef)

...but now, instead of better type inference, I get the error.

@whzx5byb
Copy link

whzx5byb commented Jul 10, 2021

See #14107

The call signature of test only contains two item, and it can't accept a boolean input.

{
  (input: true): "true"
  (input: false): "false"
}

To produce your expected behavior, you should add a call signature.

function test(input: true): "true"
function test(input: false): "false"
function test(input: boolean): "true"|"false"
function test(input: boolean): "true"|"false" {
  return input.toString() as "true"|"false"
}

function test2(): boolean {
  throw new Error("not implemented")
}

const a: boolean = test2()
test(a) // It works now!

Playground

@RyanCavanaugh RyanCavanaugh added the Duplicate An existing issue was already created label Jul 12, 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

4 participants