Cause of the issue
In elixir, parentheses in function calls are not mandatory (although desirable.) That said, the code def foo(bar baz) do ... is being parsed and treated as def foo(bar(baz)) do ... because the parser suggests omitted parentheses in call to the function bar. You should have got a warning from the compiler, saying exactly that. Warnings are supposed to be read and eliminated.
Quick fix
As it is pointed out by @peaceful-james, pattern matching inside parentheses would do.
def do_handle(%RequestParams{} = params, _context) do
“Instead of”
You wrote
def do_handle(params %RequestParams{}, _context) do
# instead of
# def do_handle(%{ "code" => code, "name" => name}, _context) do
Even if it was syntactically correct, the code above is not equivalent to the code below. The code below would accept any map, having two keys "code" and "name", while the code above allows instances of RequestParams only. One might also make the code below more strict with:
def do_handle(%RequestParams{code: code, name: name}, _) do
Struct keys
But structs in elixir cannot have anything but atom as a key. That said, if your initial code accepted %{"code" => _} there is no way to turn it into accepting a struct without modifying the calling code.
Typed stuff
Types are not the first-class citizens in elixir. I personally find it appropriate. You should start with understanding the language, OTP principles, the paradigm of the language and only after that decide whether you want and/or need types at all.