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

Type mis-match in destructuring of @optional field #5472

Closed
mununki opened this issue Jun 26, 2022 · 10 comments
Closed

Type mis-match in destructuring of @optional field #5472

mununki opened this issue Jun 26, 2022 · 10 comments

Comments

@mununki
Copy link
Member

mununki commented Jun 26, 2022

This is related #5423 #5452

type t0 = {@optional x: int}
let f0: t0 = {x: 1} // x: option<int>
let {x} = f0 // x: int instead option<int>

I think there's a type mis-match after destructuring. Isn't it correct that type of x is option<int>?

@cristianoc
Copy link
Collaborator

Not sure what's in the comments is accurate: in the f0 case it's still true x:int. You can check that {x:x} works i.e. {x} works, when x has type int.
But there's an implicit mismatch in that f0.x has type option<int>. That is unavoidable I'm afraid.

@mununki
Copy link
Member Author

mununki commented Jun 26, 2022

// definition
type props<'name> = { @optional name: 'name } // 1
let make = ({ name }: props<_>) => name->Belt.Option.getWithDefault("")->React.string // 2

// application
React.createElement(Foo.make, {name: "Foo"}) // Error, wanted: option<string>

I encountered this issue when I write the jsx ppx v4. The name is inferred to option<string> at 2. That is correct. The props is inferred to type props<'name> = { name: option<'name> } at 1. In this case, I guess that the type of props.name is inferred to option<option<name> finally. So, the name should be Some("Foo") in the application site.

// correct
<Foo name="Foo">

// wrong
<Foo name=Some("Foo") />

@cristianoc
Copy link
Collaborator

cristianoc commented Jun 26, 2022

What's the original component definitions? Looks like this is what was intended:

module Foo = {
  // definition
  type props<'name> = {@optional name: 'name} // 1
  let make = ({name: @optional name}: props<_>) => name->Belt.Option.getWithDefault("")->React.string // 2
}

@mununki
Copy link
Member Author

mununki commented Jun 27, 2022

The original definition is below.

@react.component
  let make = (~name=?) => {
    <div> {name->Belt.Option.getWithDefault("")->React.string} </div>
  }

@mununki
Copy link
Member Author

mununki commented Jun 27, 2022

{name: @optional name}: props<_>

This would work, unless the refmt removes the type annotation. I'll fix the ppx v4 accordingly.

@mununki
Copy link
Member Author

mununki commented Jun 27, 2022

Back to the first example, can user add the type annotation in this case? At least, when they want.

type t0 = {@optional x: int}
let f0: t0 = {x: 1}
let {x: @optional x} = f0 // add type annotation

@cristianoc
Copy link
Collaborator

```rescript
{name: @optional name}: props<_>

This would work, unless the refmt removes the type annotation. I'll fix the ppx v4 accordingly.

Yes I've noticed the issue with formatting, will bring it to the syntax repo. And then to the editor repo which vendors it.

@cristianoc
Copy link
Collaborator

Back to the first example, can user add the type annotation in this case? At least, when they want.

type t0 = {@optional x: int}
let f0: t0 = {x: 1}
let {x: @optional x} = f0 // add type annotation

Yes they can write type annotations.

@mununki
Copy link
Member Author

mununki commented Jun 27, 2022

Checked! rescript-lang/syntax#582
Thanks!

@mununki mununki closed this as completed Jun 27, 2022
@cristianoc
Copy link
Collaborator

The issue about formatting: rescript-lang/syntax#583

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