Type duplication between interface file and implementation

Hi,
New to rescript and first post.
What do we think about type duplication between .resi interface files and implementation, I can see that becoming hard to maintain.
Did I miss a way of doing that?
I created an interface file only to export a default value (reproducing existing code to see what that looks like), but that forced me to add and duplicate all needed types. So the types are present in both the interface file and the implementation file.
Any advice?

type entitlement = {
  purchased: array<string>,
  source: string,
  failedAvailabilityChecks: array<string>,
}
type tokenType = | @as("bearer") Bearer
type authResponse = {
  entitlement: entitlement,
  emailVerified: bool,
  tokenType: tokenType,
  accessToken: string,
  refreshToken: string,
  profileToken: string,
}
let default: (string, string) => promise<authResponse>

In my opinion it’s an issue that should be solved by a better IDE support, but if you’re looking for a solution nevertheless, there’s an easy way, define the types of your file
A.res in a third file (called A_Types.res for example), and then you can include it both in your implementation and interface files:

module A_Types = {
  type entitlement = {
    purchased: array<string>,
    source: string,
    failedAvailabilityChecks: array<string>,
  }
  type tokenType = | @as("bearer") Bearer
  type authResponse = {
    entitlement: entitlement,
    emailVerified: bool,
    tokenType: tokenType,
    accessToken: string,
    refreshToken: string,
    profileToken: string,
  }
}

module A: {
  include module type of A_Types
  let default: (string, string) => promise<authResponse>
} = {
  include A_Types
  let default = (a, b) => // your implementation here
}

playground link

2 Likes

Interesting, thanks for the reply, I’ll try that!