Typle (Typle v0.3.1)

View Source

Expression-level type query library for Elixir 1.20+.

Reads inferred type signatures from compiled .beam files and performs best-effort type inference to answer "what type does the compiler think this expression has at line N, column C?"

Before inference, all macros in function bodies are expanded via ExPanda, so pipe chains, unless, use directives, and library DSLs are resolved to their underlying forms. When expansion fails, the original AST is preserved and inference falls back to its existing best-effort handling.

Usage

# Point query
Typle.type_at("lib/my_app/user.ex", 15, 5)
#=> {:ok, %Typle.Type{kind: :binary}}

# Full module map
Typle.types_for(MyApp.User)
#=> {:ok, %{{15, 5} => %Typle.Type{kind: :binary}, ...}}

# Read function signatures from a compiled module
Typle.signatures(Integer)
#=> {:ok, [%{fun: :to_string, arity: 1, clauses: ...}, ...]}

For deeper inference using compiler internals (opt-in, unstable), see Typle.Unstable.

Summary

Functions

Looks up the return type of a function call.

Reads function signatures from a compiled module's .beam file.

Returns the inferred type at the given file position.

Returns all inferred types for a module.

Returns all inferred types for a source file.

Functions

return_type(module, function, arity, opts \\ [])

@spec return_type(module(), atom(), non_neg_integer(), keyword()) :: Typle.Type.t()

Looks up the return type of a function call.

Queries the signature store for module.function/arity and returns the inferred return type.

Options

  • :unstable - accepted for API consistency but currently has no effect (return types are always resolved via the signature store)

signatures(module_or_path, opts \\ [])

@spec signatures(
  module() | String.t(),
  keyword()
) :: {:ok, [Typle.Beam.signature()]} | {:error, term()}

Reads function signatures from a compiled module's .beam file.

Returns the decoded type signatures as stored in the ExCk chunk.

Options

  • :unstable - accepted for API consistency but currently has no effect (signatures are always read from BEAM chunks)

type_at(file, line, col, opts \\ [])

@spec type_at(String.t(), non_neg_integer(), non_neg_integer(), keyword()) ::
  {:ok, Typle.Type.t() | %{type: Typle.Type.t(), expr: String.t() | nil}}
  | {:error, term()}

Returns the inferred type at the given file position.

Uses the stable inference engine (AST walking + signature store).

Options

  • :unstable - when true, uses the compiler-replay engine from Typle.Unstable for deeper inference (default: false)
  • :expr - when true (default), returns a map with both the type and the source expression string: {:ok, %{type: Type.t(), expr: String.t() | nil}}. When false, returns {:ok, Type.t()} (legacy behaviour).

types_for(module, opts \\ [])

@spec types_for(
  module(),
  keyword()
) :: {:ok, map()} | {:error, term()}

Returns all inferred types for a module.

Returns a map of {line, col} => Typle.Type.t() for each expression in the module's source file.

Options

  • :unstable - when true, uses the compiler-replay engine from Typle.Unstable for deeper inference (default: false)
  • :expr - when true (default), each value in the map becomes %{type: Type.t(), expr: String.t() | nil} instead of bare Type.t().

types_for_file(file, opts \\ [])

@spec types_for_file(
  String.t(),
  keyword()
) :: {:ok, map()} | {:error, term()}

Returns all inferred types for a source file.

Options

  • :unstable - when true, uses the compiler-replay engine from Typle.Unstable for deeper inference (default: false)
  • :expr - when true (default), each value in the map becomes %{type: Type.t(), expr: String.t() | nil} instead of bare Type.t().