RFC: More general type checking for structural typings

It should be possible to ship this as experimental feature in the next release.

1 Like

Hello! It’s very nice to see the progress of @optional and how it became a more fine-grained @obj. Thank you for it!

I’d like to share a thought about making it even more concise and consistent with other parts of the language. Namely, the optional function args. I see they have somewhat common semantics, so could they have a common syntax as well?

With your implementation, a developer have the following opportunities:

type t = {
  x: int,
  @optional y: int, // this is how an optional field is declared
}

// basic usage, very intuitive
let v1 = { x: 3 }
let v2 = { x: 3, y: 4 }

// unwrapping an option
let v3 = { x: 3, y: @optional None }
let y: option<int> = Some(4)
let v4 = { ...v1, y: @optional y }

Wouldn’t it be nice if instead of @optional one can use the familiar ? token known from optional args?

type t = {
  x: int,
  y: int=?, // same as in function declarations
}

// basic usage, same as before
let v1 = { x: 3 }
let v2 = { x: 3, y: 4 }

// unwrapping an option
let v3 = { x: 3, y: ?None } // like in functions
let y: option<int> = Some(4)
let v4 = { ...v1, y: ?y } // like in functions
let v5 = { ...v1: ?y } // even punning might be supported

This is just a thought. I know, implementing such syntax is harder because it requires touching the syntax layer. Nevertheless, perhaps it would be possible some day in future, even after the current @optional way will be released and settled down.

6 Likes

Definitely putting a syntax layer on top is something worth considering .
What needs to happen is for someone to investigate how a dedicated syntax fits within the existing parser/printer, so a prototype can be shown to people.

1 Like

This is not a new concept, so familiarity with e.g. TypeScript or other languages is also something to consider.

1 Like

I’m all for this new syntax, it would be coherent with the existing rescript syntax and would be easily understood in my opinion.

I originally had the false impression that making @obj the default would mean that we would not be guided when adding new option fields, but given those fields have to explicitly annotated with @optional then I guess it’s alright!

For the breaking changes it would bring in the generated code, I guess it could be made more likely by the usage of if ('field' in obj) in typescript, but God what a brittle logic anyway, and it would not break existing code base given again you’d have to annotate the field.

As a last remark, the RFC has evolved from structural typing (for objects) to nominal typing (for records), shouldn’t we rename this thread?

2 Likes

Notice this proposal does not change existing code at all, so is non-breaking.
You only opt into semantic difference if you use @optional on some fields, but then it’s a different type altogether.

Renaming sounds like a good idea.

1 Like

Would this syntax ever work?

type t = {
  x: int,
  y: int = 3
}

Possibly. Though in realistic cases one is not likely to know what values to initialise with at compile time.

Update: discovered there was a missing bit in the proposal for fields with @optional record: a treatment for patterns.

Here is the proposal now:

6 Likes

How do you match the absence of a property

The same as you construct a value with the property None.
Patterns === expressions.

Surface syntax for records with optional fields: https://github.com/rescript-lang/syntax/pull/588

8 Likes