In Elixir, structs can only ever have the keys that you assigned to it in the defstruct
macro.
iex(1)> defmodule Foo do
...(1)> defstruct [:a, :b]
...(1)> end
{:module, Foo,
<<70, 79, 82, 49, 0, 0, 5, 184, 66, 69, 65, 77, 65, 116, 85, 56, 0, 0, 0, 180,
0, 0, 0, 18, 10, 69, 108, 105, 120, 105, 114, 46, 70, 111, 111, 8, 95, 95,
105, 110, 102, 111, 95, 95, 7, 99, 111, ...>>, %Foo{a: nil, b: nil}}
iex(2)> struct = %Foo{a: :a}
%Foo{a: :a, b: nil}
iex(3)> %{struct | b: :b}
%Foo{a: :a, b: :b}
iex(4)> %{struct | something: :b}
** (KeyError) key :something not found in: %Foo{a: :a, b: nil}
(stdlib) :maps.update(:something, :b, %Foo{a: :a, b: nil})
(stdlib) erl_eval.erl:259: anonymous fn/2 in :erl_eval.expr/5
(stdlib) lists.erl:1263: :lists.foldl/3
iex(4)> key = :b
:b
iex(5)> %{struct | key => :c}
%Foo{a: :a, b: :c}
iex(6)> key = :different
:different
iex(7)> %{struct | key => :d}
** (KeyError) key :different not found in: %Foo{a: :a, b: nil}
(stdlib) :maps.update(:different, :d, %Foo{a: :a, b: nil})
(stdlib) erl_eval.erl:259: anonymous fn/2 in :erl_eval.expr/5
(stdlib) lists.erl:1263: :lists.foldl/3
You can use %{struct | key => value}
just fine as long as the value of key
is one of the keys that struct has.