summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Long <him@nathanmlong.com>2023-03-22 09:48:49 -0400
committerGitHub <noreply@github.com>2023-03-22 14:48:49 +0100
commite2a207a4559527c43165b47ff8e7c981ae039112 (patch)
tree1e78aed18ac3729c47d1b69389ee0b3e06530ec1
parentbb1c89536d79ecf56ad4c9ebb6a3fad8dadbb203 (diff)
downloadelixir-e2a207a4559527c43165b47ff8e7c981ae039112.tar.gz
Examples of composing a keyword list type (#12482)
Examples by Myron Marston and Michał Muskała in https://elixirforum.com/t/typespecs-best-way-to-spec-keyword-lists/2991
-rw-r--r--lib/elixir/pages/typespecs.md26
1 files changed, 26 insertions, 0 deletions
diff --git a/lib/elixir/pages/typespecs.md b/lib/elixir/pages/typespecs.md
index 7eea7e0fc..74fa2fd0a 100644
--- a/lib/elixir/pages/typespecs.md
+++ b/lib/elixir/pages/typespecs.md
@@ -172,6 +172,32 @@ it is common to end a map type with `optional(any) => any`.
Note that the syntactic representation of `map()` is `%{optional(any) => any}`, not `%{}`. The notation `%{}` specifies the singleton type for the empty map.
+### Keyword Lists
+
+Beyond `keyword()` and `keyword(t)`, it can be helpful to compose a spec for an expected keyword list.
+For example:
+
+
+```elixir
+@type option :: {:name, String.t} | {:max, pos_integer} | {:min, pos_integer}
+@type options :: [option()]
+```
+
+This makes it clear that only these options are allowed, none are required, and order does not matter.
+
+It also allows composition with existing types.
+For example:
+
+```elixir
+type option :: {:my_option, String.t()} | GenServer.option()
+
+@spec start_link([option()]) :: GenServer.on_start()
+def start_link(opts) do
+ {my_opts, gen_server_opts} = Keyword.split(opts, [:my_option])
+ GenServer.start_link(__MODULE__, my_opts, gen_server_opts)
+end
+```
+
### User-defined types
The `@type`, `@typep`, and `@opaque` module attributes can be used to define new types: