What does this type mean?

Hi, I recommend posting all code samples in plain text formatted as code. You can use triple-backticks before and after the code to format it. E.g.,

let x = 1

This is more accessible than posting images.

5 Likes

Pretty sure it’s the type representing an object with no fields.

playground

let f = (x: {..}) => x

let y = f({"a": 1})
let y' = f({"b": 1, "hi": "apple"})

let g = (x: {.}) => x

// Error
// This has type: {"a": int}
// Somewhere wanted: {.}
// The second object type has no field a
let z = g({"a": 1})

(I found out about it by looking in the compiler source.)

Which I suppose must be the type of your Ui.make given the type of React.createElement is (React.component<'a>, 'a) => React.element.

1 Like

What are you doing with Ui.make that you would give it that type?

@Ryan Thanks, but i still want to know how to create a value with type {.}.
Here is the playground, the line 36 shows calling Ui.make(), this line of code can not be compiled for the reason Empty record literal {} should be type annotated or used in a record context. in rescript 10.1.4

https://rescript-lang.org/try?version=v10.1.2&code=LYewJgrgNgpgBAVQJZwLxwN4Cg5wAIBOMAhgMYAuAdKSMAA4gB2Mj5Ocs5cwxA1vOgAUASjQA+TO1yc4ggM4ALEAHcAIkmJQQAcwA0cOTHIBlJWo1bto9ACUSFShEPHyxcjEEB9cXABmmw2EpOGC7MionGABRX18YCgBGQREfbFx0gyNTFXVNHS8fcgIIGCCM3AA5JhhggF99AG0AXSDgpF8DM1zLSXK4AB4wJAA3MQwAIiRGYZg5ciRtNyQmcYBaMTCHOYIp7Vr+gHoh0bq4GChDXvLNqkZoKDr2WqxnrDxtLQAjTTOAD3cCIwfmAQKQIMAWOQAFxwADkILBENYaDg4wR4Mh4ywWHIAE86PBPuBcW9tEY-gCgVA4ESwLiYfDQRjkagJLTcSjxuysTJ2Sj0UjyOt2di8IZGGAKTBAZosMQ6ASJQBhBRIKBgGGCdn6VS0SjnGCC6wSCCMJBcdDjeWKsAqtVgLFvcWSmD-aVUkJEUAzO3qzXauC64D62BGnym82cr0gH2q9WOmQgRUASWms3mi3mTBRKVZV3YMhorGIU2l-KZgoa41IRDc0VDmKagjRI3G+nG4zKNOJ62tLFtcbAgiLrlLBC7MimMzmCyW2fQ-WQcAOYnYBwOHHJBpRyEoPH4ggwtS7N1UAHkALKUIgS6WCKfp2dZxj6Ecl5jj9i5iRpdLs9bRrG9rDkwo4fl2zzPEAA

I can’t reproduce that error you’re getting with the code you show. It works fine if you uncomment the line. See playground.


Regardless of that, the Ui.make isn’t taking an object with no fields anyway…it’s taking a record with no fields. Different in rescript but not in compiled js.

Type of the Ui module you show

module Ui: {
  type props = {} // record with no fields
  let make: props => React.element
}

As far as I can tell from looking at code and experimenting (I can find no docs about it, and don’t work on the compiler–one of those folks may hopefully chime in and correct me if I’m wrong), there is this:

  • {} : record with no fields
  • {.} : object with no fields

If you want to create an empty object you can always do @new external emptyObj: unit => {.} = "Object" or something similar.

To create the record with no field you can do {}. E.g., (playground)

type x = {}

let f = (x: x) => x

// Used in a record context.
let y = f({})

// Annotated
let x: x = {}

Now what is interesting is that this doesn’t work:

let f = (x: {}) => x

let y = f(({}: {}))

I guess you have to write the type explicitly for that?

And also interesting is that when you format it, it changes the {} to {.}. I don’t know, but this may be a bug.

2 Likes

It can compiled successfully in the playground with rescript version of 10.1.2, but failed with rescript version of 10.1.4 in my computer envrionment(windows11 wsl ubuntu22.04)

See the screen shot below:

If the Ui code you showed is the same as the one in the playground, then it will work also on 10.1.4 if you pass in {} to the Ui.make({}) like that.

Now as to why it is saying it needs type {.}, that does seem weird. The react component should be taking a props record. When I run it locally, as you have, passing in unit rather than props, I get Somewhere wanted: Ui.props as it should be. Is your Ui code in that screen shot exactly the same as you put in the playground? Maybe it is something with the jsx version or rescript-react version you’re using? You could post those versions as well.

(Also, not to be annoying about it, but yawaramin is right, if you could put plain text for your code snippets it would be helpful.)

1 Like

Thanks, the code in the playground is a little different with the code of the latest screen shot i put, but the differences are some irrelavant code(my code base is relativily huge, i have to cut some dependent code to make it compiled in the playground). I guess the reason why this code can be compiled in the playground is that the jsx version is v4 by default while my code base is v3.

The playground
image

My code base

{
  "name": "mng-gif-maker-v6",
  "version": "0.1.0",
  "sources": [
    {
      "dir": "pages",
      "subdirs": false
    },
    {
      "dir": "res",
      "subdirs": true
    },
    {
      "dir": "mng-gif",
      "subdirs": [
        "som-res"
      ]
    }
  ],
  "package-specs": {
    "module": "commonjs",
    "in-source": true
  },
  "suffix": ".bs.js",
  "reason": {
    "react-jsx": 3
  },
  "bs-dependencies": [
    "@rescript/react",
    "rescript-webapi",
    "rescript-recoil",
    "@ryyppy/rescript-promise",
    "rescript-mngutils"
  ]
}

After changing the jsx version from v4 to v3, the playground code can not be compiled also.

@@jsxConfig({ version: 3, mode: "automatic" })
1 Like

Oh yeah that makes sense…with v3 Ui module type is

module Ui: {
  let makeProps: (~key: string=?, unit) => {.}
  let make: {.} => React.element
}

So you need something like this to get the types to work out.

let _ele = Ui.make(Ui.makeProps(~key="someting", ()))
let _y: 'a = React.createElement(Ui.make, Ui.makeProps(~key="whatever", ()))

Out of curiosity, are you avoiding the jsx for a reason, like just for learning or you don’t like it?

1 Like

No, i would use jsx in most cases, but there are some cases that you need rendering a component manually in pure js side not in the rendering lifetime of react, just like message tips and global loading components.