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

Issues with @spec! on auto-generated type like TypedEctoSchema #172

Closed
eriknaslund opened this issue Jan 19, 2023 · 2 comments
Closed

Issues with @spec! on auto-generated type like TypedEctoSchema #172

eriknaslund opened this issue Jan 19, 2023 · 2 comments

Comments

@eriknaslund
Copy link

eriknaslund commented Jan 19, 2023

Hi there,

TypeCheck looks really interesting, but I'm afraid I'm having some issues when trying to make use of it.
I'm trying to use it together with TypedEctoSchema, but I'm getting compile errors. Could this possibly be because TypeCheck "runs before" TypedEctoSchema gets the chance to generate the typespecs? Any workaround available?

Actual behaviour

I get a function Xxx.User.t/0 is undefined or private' error. when using TypeCheck together with TypedEctoSchema

Expected behaviour

TypeCheck should work with auto-generated typespecs like those coming from TypedEctoSchema.

Example code

defmodule Xxx.Accounts do
  use TypeCheck
  alias Xxx.User

  @spec! get_user_by_email(String.t()) :: User.t() | nil
  def get_user_by_email(email) do
    Repo.get_by(User, email: email)
  end
end


defmodule Xxx.User do
  use TypedEctoSchema
  import Ecto.Changeset

  typed_schema "user" do
    field :email, :string
    ...    
  end
end
@Qqwy
Copy link
Owner

Qqwy commented Jan 19, 2023

Hi there!

TypeCheck's checking functionality requires functions that return TypeCheck structs to exist as well as specs. This is necessary because these structs capture a lot of metadata that cannot be found in plain specs by themselves. TypeCheck.External exists which tries to turn plain specs into TypeCheck structs, but it by necessity works on a 'best-effort' basis, and it cannot be combined with the type!/ spec! macros (that run at compile-time); you'll have to use either TypeCheck.dynamic_conforms! or TypeCheck.External.enforce_spec! inside your function bodies.

You're not the first person who'd like to integrate TypeCheck and TypedEctoSchema. There is a work-in-progress PR on the TypedEctoSchema repo to enable the automatic creation of TypeCheck types from a call to typed_schema.

Until this PR is finished, the following workarounds exist:

  1. Write the types in your Ecto's struct module out manually using type! together with @autogen_typespecs: false. This will give you all of TypeCheck's functionality, but it obviously goes against the principle of TypedEctoSchema doing the typespec-generation for you.
  2. Fetch the specs generated by TypedEctoSchema using the functions in TypeCheck.External and using TypeCheck.dynamic_conforms! or TypeCheck.External.enforce_spec! inside your functions to check against them.

@eriknaslund
Copy link
Author

That's awesome! Thanks a bunch for the in-depth reply @Qqwy.

I checked for issues in the TypeCheck repo, but failed to find any.
I should of course have looked in the TypedEctoSchema repo as well, and I would have found the PR/Issue, my bad.

I'll close this issue hoping that it's OK, since there's already a PR in progress in the TypedEctoSchema repo.

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