<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Daniel Little</title>
    <description>The latest articles on DEV Community by Daniel Little (@daniellittledev).</description>
    <link>https://dev.to/daniellittledev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F158596%2F5a3ab92b-e4a3-42e7-9486-b1c6f3019191.jpg</url>
      <title>DEV Community: Daniel Little</title>
      <link>https://dev.to/daniellittledev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/daniellittledev"/>
    <language>en</language>
    <item>
      <title>Don't Ignore Your Functions</title>
      <dc:creator>Daniel Little</dc:creator>
      <pubDate>Mon, 05 Oct 2020 10:31:00 +0000</pubDate>
      <link>https://dev.to/daniellittledev/don-t-ignore-your-functions-83a</link>
      <guid>https://dev.to/daniellittledev/don-t-ignore-your-functions-83a</guid>
      <description>&lt;p&gt;Ignoring return values can often be dangerous in subtle ways but you may be so used to doing it that you don't even notice anymore. It's likely that at some point you have run into an issue caused by forgetting to use the return value of a function. It's even more likely you throw away the return values of functions without thinking too much about it. Most of the time there's no real impact of doing so, and if there is it's certainly not immediate. But if you find yourself doing this often it is important to ask why. Presumably, the function is returning this value for a reason? Is there something wrong with the design of the API, or are you missing something important?&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding to a date doesn't change it
&lt;/h2&gt;

&lt;p&gt;Have you ever seen code like this?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var date = new DateTime(2000, 01, 01);

date.AddYears(1);
Console.WriteLine($"{date.ToShortDateString()}");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It looks pretty straightforward, but there's a bug in this code. If you're familiar with the dotnet &lt;code&gt;DateTime&lt;/code&gt; API it might be an obvious one but it can be subtle and confusing if you've never used it before.&lt;/p&gt;

&lt;p&gt;The issue is that when you call &lt;code&gt;AddYears&lt;/code&gt; it doesn't modify the date, instead it returns a brand new date. Therefore when &lt;code&gt;WriteLine&lt;/code&gt; is called the value will still say &lt;code&gt;2000/01/01&lt;/code&gt; instead of &lt;code&gt;2001/01/01&lt;/code&gt; like you may have expected.&lt;/p&gt;

&lt;p&gt;To get this to work correctly you'd have to capture the new date by assigning the new value to the date variable, like so.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var date = new DateTime(2000, 01, 01);

date = date.AddYears(1);
Console.WriteLine($"{date.ToShortDateString()}");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So why does &lt;code&gt;AddYears&lt;/code&gt; return a new date object instead of adding a year to the existing date? It does this because date is an immutable type. This means that once you create a date you can never modify or change it, in any way. If you need a different date you'll always need to create a new one.&lt;/p&gt;

&lt;p&gt;Immutability itself is a very useful technique because it can help manage complexity due to limiting the possibilities you have to consider; there is only one way to change the date, replace it. However, issues like the example above can be hard to find if you're not looking for them. Wouldn't it be great if the C# compiler could detect issues like this and prevent you from making the mistake in the first place!&lt;/p&gt;

&lt;h2&gt;
  
  
  Async and you forgot to await
&lt;/h2&gt;

&lt;p&gt;Let's look at a different problem for a moment. Say you had an async function which calls out to two async functions but you forget to await one of them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;async Task&amp;lt;ActionResult&amp;lt;Resource&amp;gt;&amp;gt; GetResource(string id) {

    AuditRequestAsync(id); // Forgot to await this, oops

    return await LoadResourceAsync(id);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, you'll get a warning from the C# compiler telling you that there might be a missing await. This is fantastic because the majority of the time this is almost certainly a bug. However, depending on how closely you monitor your warning, it's still possible to compile the app with the default compiler options. But what happens if we have the same function but without the async keyword, like so.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Task&amp;lt;ActionResult&amp;lt;Resource&amp;gt;&amp;gt; GetResource(string id) {

    AuditRequestAsync(id);

    return LoadResourceAsync(id);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Semantically this function is exactly the same, it also suffers from the same bug but this time there's not even a warning. I've found this kind of issue to more common than it appears because a function can start off by only returning a task without needing the async keyword. In the example above if the &lt;code&gt;AuditRequestAsync&lt;/code&gt; function was added later on, or by a different author, they could forget to add the async keyword and the program will still happily compile.&lt;/p&gt;

&lt;p&gt;To make matters worst, the function might work in some cases, but fail in others. The &lt;code&gt;AuditRequestAsync&lt;/code&gt; function will still run, but without &lt;code&gt;await&lt;/code&gt; there is no guarantee the caller will still be around when it finishes. In some cases you might get an error regarding &lt;code&gt;multiple active result sets&lt;/code&gt; if they both make database calls. In others, you might not notice anything is wrong at all. Issues like these can often lie dormant until other changes trigger them, or result in indeterministic (or at the very least non obvious) behaviour making them extremely hard to track down and fix.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implicitly ignoring functions is dangerous
&lt;/h2&gt;

&lt;p&gt;What these examples have in common is that the value returned by a function (&lt;code&gt;AddYears&lt;/code&gt; and &lt;code&gt;AuditResourceRequestAsync&lt;/code&gt;) was implicitly ignored, resulting in a bug. If the compiler had issued a warning or an error indicating that the value was unused or implicitly ignored these issues could have been caught earlier or prevented entirely.&lt;/p&gt;

&lt;p&gt;There are also many more scenarios that suffer from this problem. For example using APIs like LINQ, Reactive Extensions, using Structs, and all immutable types, are cases where forgetting to use the value is almost certainly a bug. Even regular functions, particularly those that return values without side effects would benefit from making it obvious that a return value was ignored or forgotten.&lt;/p&gt;

&lt;h2&gt;
  
  
  Explicitly ignoring functions is safer
&lt;/h2&gt;

&lt;p&gt;Instead of implicitly throwing away unused values, if we don't want to use a value we should explicitly discard it.&lt;/p&gt;

&lt;p&gt;To help catch unused values you could use a custom analyzer to create a warning for all unused values, not just a missing await inside an async function. There are no analyzers that do this yet, however, there are a few similar existing analyzers for some of these cases, such as &lt;a href="https://docs.particular.net/nservicebus/operations/nservicebus-analyzer"&gt;async await&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Once there are warnings for unused return values it becomes clearer that an unused value is either a bug or something that can be explicitly discarded.&lt;/p&gt;

&lt;p&gt;A task, for example, would result in a warning about a possible missing await. If you do want to ignore the task then you can use a &lt;code&gt;standalone discard&lt;/code&gt; to let others know you don't care about it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;_ = Task.Run(() =&amp;gt; { ... }) // Explicitly discard the result
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes it clear that you made a conscious decision not to use the value. It shows other developers that a decision was made not to use the value as opposed to forgetting to use it.&lt;/p&gt;

&lt;p&gt;When someone else reads that code it is the difference between:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Did they&lt;/em&gt; &lt;em&gt;forget to use the return value? I'll need to investigate, versus...&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;They've chosen to ignore the&lt;/em&gt; &lt;em&gt;return value&lt;/em&gt;. &lt;em&gt;I can move on.&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Making things more explicit will prevent bugs and save you and others a lot of time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Would this really work
&lt;/h2&gt;

&lt;p&gt;There's a lot of code out there today which was written without explicit discards in mind. And I don't expect the world of C# to change drastically overnight. Nevertheless, the aim of this article is to get more you interested in an analyzer that warns developers about unused return values in the same way your editor warns you about an unused variable today.&lt;/p&gt;

&lt;p&gt;You may still be wondering if so much C# code was written without explicit ignores in mind, would this be even practical to do in C#? Recently I've been doing a lot of dotnet development using F# which does emit compiler warning if a function return value is not used. So I can say that even with the dotnet as it exists today, I have been pleasantly surprised. I didn't need to discard half as many values as I thought I would.&lt;/p&gt;

&lt;p&gt;The large majority of code didn't need a single discard. There were only a few cases where I needed to use a discard, for example discarding the value at the end of a mutable fluent API.&lt;/p&gt;

&lt;p&gt;In that case, I would use an extension method to explicitly "cap off" the expression.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;builder
    .RegisterType&amp;lt;HttpClient&amp;gt;().AsSelf()
    .InstancePerLifetimeScope()
    .Ignore() // &amp;lt;- Takes a type &amp;lt;T&amp;gt; and returns a void
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I did however still run into at least one bug where I explicitly discarded a value that I shouldn't have. In the end, I found that even explicitly discarding values was something that should be done sparingly. Whenever I discarded a return value I found myself rethinking the code instead.&lt;/p&gt;

&lt;p&gt;I was more likely to use or log a status code or return code.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var response = await httpClient.PostAsync(url, null);
log.Information("Responded with {StatusCode}", response.StatusCode);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If I wanted to run a task in the background I kept the task in a Task service and it simplified error handling for all background tasks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BackgroundService.Register(async () =&amp;gt; {...})

// Instead of

_ = Task.Run(async () =&amp;gt; {...}) // Hope you handled the exceptions in here
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If I used the builder pattern or a fluent API I considered using an immutable API and returning the value instead of a using a mutable one. For example using LINQ vs using the List API.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public IEnumerable&amp;lt;Out&amp;gt; GetResults(IEnumerable&amp;lt;In&amp;gt; items) =&amp;gt; items
    .Where(x =&amp;gt; ...)
    **.Select(x =&amp;gt; ...)
    .OrderBy(x =&amp;gt; ...)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I'm also cautious of functions that don't return values but that's another story.&lt;/p&gt;

&lt;h2&gt;
  
  
  I'm interested but maybe not convinced
&lt;/h2&gt;

&lt;p&gt;Whenever I first stumble across a new concept or technique I find that I need to play with it for a while to start to get a good feel for how it works. Have a go at building an analyzer and see where the warnings are. Try writing a program from scratch with the warnings on. Turn on warnings as errors so you aren't tempted to take shortcuts and follow where the analyzer takes you.&lt;/p&gt;

&lt;p&gt;But most importantly, if you find yourself discarding values without using them, ask yourself why.&lt;/p&gt;

</description>
      <category>safety</category>
      <category>functions</category>
      <category>csharp</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>Type-Safe Hypermedia Controls</title>
      <dc:creator>Daniel Little</dc:creator>
      <pubDate>Sun, 12 Jul 2020 08:00:00 +0000</pubDate>
      <link>https://dev.to/daniellittledev/type-safe-hypermedia-controls-8le</link>
      <guid>https://dev.to/daniellittledev/type-safe-hypermedia-controls-8le</guid>
      <description>&lt;p&gt;Hypermedia Controls in REST provide links and actions with each response pointing to related resources. This concept is a powerful tool that enables the server to remain in control of links and access. If you're not sure what I mean by this, take a moment to read my previous article on my approach regarding &lt;a href="https://dev.to/practical-hypermedia-controls"&gt;Practical Hypermedia Controls&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Enter Typescript. Adding types to JavaScript allows us to write safer code, so naturally I wanted to figure out how to make a Hypermedia Controls type-safe. Typically when writing a type-safe API you might start out with something like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const api = (fetch: Fetch) =&amp;gt; ({
  getAccount: async (id: string) : AccountResource =&amp;gt; {
    const response = await fetch(`/account/${id}`, jsonGetOptions);
    return response.json() as AccountResource;
  }
  updateAccount: async (account: AccountResource) : AccountResource =&amp;gt; {
    const response = await fetch(`/account/${account.id}`, jsonPutOptionsWith(account));
    return response.json() as AccountResource;
  }
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the &lt;code&gt;Request&lt;/code&gt; and &lt;code&gt;Response&lt;/code&gt; types are strongly typed but the URL is hardcoded and you can't tell when you'd have access or who has access to this endpoint. Using Hypermedia Controls can provide that missing context. Links and actions are related to a resource, and the server can dictate if or when the various links and actions are available.&lt;/p&gt;

&lt;p&gt;In order to see how to combine these two concepts, let's look at what the usage of type-safe Hypermedia controls would look like.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Fetch a root resource
const account = await fetchAccount(url)
const accountHypermedia = accountHypermedia(account)

const accountUpdate = { ...account, email: "daniellittle@elsewhere" }

// Invoke the Update action
const updatedAccount = await accountHypermedia.actions.update.call(updatedAccount) // &amp;lt;- Typechecked!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example the account email address is being updated and then the Hypermedia Controls are used to update the resource. Fetching the account resource contains the raw Hypermedia Controls but passing the resource into the &lt;code&gt;accountHypermedia&lt;/code&gt; function transforms the hypermedia into a type safe API style object. There are a few interesting things happening here, so let's peel back the covers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Types for Links and Actions
&lt;/h2&gt;

&lt;p&gt;First, Let's take a look at what the &lt;code&gt;AccountResource&lt;/code&gt; type looks like.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export type AccountResource = {
  id: Identifier
  username: string
  name: string
  email: string

  _links: {
    self: Relationship
  }
  _actions: {
    activate?: Relationship
    deactivate?: Relationship
    update: Relationship
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Hypermedia Controls are statically defined inside of the &lt;code&gt;_links&lt;/code&gt; and &lt;code&gt;_actions&lt;/code&gt; properties which contain all the well known relationships. Looking at these relationships we can see the resource always contains a &lt;code&gt;self&lt;/code&gt; link and an &lt;code&gt;update&lt;/code&gt; action but optionally contains &lt;code&gt;activate&lt;/code&gt; and &lt;code&gt;deactivate&lt;/code&gt;. It's important to note that the types are only coupled to the names of the relationships (rels) and their optionality. The server still controls the URLs and the presence of optional relationships.&lt;/p&gt;

&lt;p&gt;Be cautious of making the types for the Hypermedia Controls too dynamic. On my first attempt at adding types for hypermedia, I used a more general dictionary type for links and actions. My thinking was that this would more accurately model the changing and dynamic hypermedia relationships a resource would have.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type Relationships = { [rel: string]: Relationship | unknown }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This assumption quickly turned out to be false and worked against the goal and benefits of strong typing. The relationships were not as dynamic as I had originally assumed. Links and actions don't change frequently, so you can safely define them as part of the type. Another downside was that you can't easily see what relationships are contextual and which ones are always present.&lt;/p&gt;

&lt;p&gt;Hypermedia is often taken a bit too far and is often associated with machine-readable metadata or form builders. My advice here is to avoid designing your types for general hypermedia clients. Instead, think of these types as representing a well defined and static contract between the client and the server.&lt;/p&gt;

&lt;p&gt;All links and actions use the &lt;code&gt;Relationship&lt;/code&gt; type which represents the relationship and its location. A relationship can be either a simple URL or a contain extra info such as the &lt;code&gt;Method&lt;/code&gt; or &lt;code&gt;Title&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export type Href = string
export type DetailedRelationship = {
  href: Href
  method?: Method
  title?: string
}
export type Relationship =
  | Href
  | DetailedRelationship
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I usually use the &lt;code&gt;DetailedRelationship&lt;/code&gt; type but sometimes it's conventient to only provide the URL for links, which typically use the &lt;code&gt;GET&lt;/code&gt; verb.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contextual Relationships
&lt;/h2&gt;

&lt;p&gt;In the &lt;code&gt;AccountResource&lt;/code&gt; above you can see there are three potential actions. The &lt;code&gt;update&lt;/code&gt; action is always available but &lt;code&gt;activate&lt;/code&gt; and &lt;code&gt;deactivate&lt;/code&gt; are optional so the client only has to check for the presence of the optional relationships. The server can then decide when these optional actions are available, enabling the actions for the client based on the state of the resource.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const account = fetchAccount(url)
const accountHypermedia = accountHypermedia(account)

if (accountHypermedia.deactivate) {
  // The account can be deactivated!

  await accountHypermedia.deactivate.call() // &amp;lt;- Also Typechecked, no request payload is needed!
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this sample, &lt;code&gt;deactivate&lt;/code&gt; has to be null checked before it can be used. The &lt;code&gt;call&lt;/code&gt; function also knows that &lt;code&gt;deactivate&lt;/code&gt; takes no payload and what the return type is.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a Hypermedia Model
&lt;/h2&gt;

&lt;p&gt;Next, let's look into the &lt;code&gt;accountHypermedia&lt;/code&gt; function, which does the heavy lifting of transforming the resource with hypermedia into a typed hypermedia model containing all the links and actions. To make the conversion easier I've also written a function &lt;code&gt;createHypermediaModel&lt;/code&gt; which helps to create the API for a resource.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type none = void // Used when a Request requires no payload (function &amp;lt;T&amp;gt;(arg: T) would need no arguments)

const accountHypermedia = createHypermediaModel((resource: AccountResource, resolve) =&amp;gt; ({
  links: {
    self: resolve&amp;lt;none, AccountResource&amp;gt;(resource._links.self)
  },
  actions: {
    deactivate: resolve&amp;lt;none, AccountResource&amp;gt;(resource._actions.deactivate),
    update: resolve&amp;lt;none, AccountResource&amp;gt;(resource._actions.update)
  }
}))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can view this code as a mapping from the resource to a set of, ready to use, functions. The resolve function takes the relationship and returns an object containing a strongly typed &lt;code&gt;call&lt;/code&gt; function as well as the &lt;code&gt;href&lt;/code&gt; and &lt;code&gt;title&lt;/code&gt; if one was provided.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resolve&amp;lt;none, AccountResource&amp;gt;(resource._links.self)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Note: In Typescript, you are able to pass through a generic function as a parameter. The &lt;code&gt;resolve&lt;/code&gt; parameter makes use of this to compose (an instance of) fetch and the request/response types.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;ResolvedRelationship&lt;/code&gt; makes it convenient to access the &lt;code&gt;href&lt;/code&gt; and other metadata if you only have access to the hypermedia model.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export type ResolvedRelationship&amp;lt;Request, Response&amp;gt; = {
  call: (request: Request) =&amp;gt; Promise&amp;lt;Response&amp;gt;
  href: string
  title: string | undefined
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I use &lt;code&gt;href&lt;/code&gt; from the &lt;code&gt;ResolvedRelationship&lt;/code&gt; to follow links to different pages by changing the URL. This means exposing the &lt;code&gt;Method&lt;/code&gt; isn't nessesary as they are always &lt;code&gt;GET&lt;/code&gt; requests.&lt;/p&gt;

&lt;h2&gt;
  
  
  Multiple Resources
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;createHypermediaModel&lt;/code&gt; function focuses on creating a hypermedia model for a single resource. In order to create a model for an entire API you can use a &lt;code&gt;createApi&lt;/code&gt; function to create a single object composing the sub-APIs for each individual resource.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export function createApi(fetch: Fetch) {
  const resolve = createResolver(fetch)

  return {
    getAccount: (url: string) =&amp;gt; resolve&amp;lt;none, AccountResource&amp;gt;(url).call(),
    accounts: accountHypermedia(resolve),

    // More models go here!
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That covers all the main pieces of using &lt;code&gt;createHypermediaModel&lt;/code&gt; to build a type-safe hypermedia API. Please let me know if you liked this approach as I'm considering wrapping this up into an npm package. However, I've glossed over the detail of how &lt;code&gt;createHypermediaModel&lt;/code&gt; works. It's mostly the glue and pluming but there are a few interesting parts. Feel free to read the apendix below if you'd like to dig deeper under the covers.&lt;/p&gt;

&lt;p&gt;That's all I have for now and as always thanks for reading!&lt;/p&gt;

&lt;h2&gt;
  
  
  Apendix: Deeper into the Code
&lt;/h2&gt;

&lt;p&gt;Here is the bulk of the code, feel free to skim over it and jump to the alaysis at the bottom.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export type JsonFetch = &amp;lt;Request, Response&amp;gt;(method: Method, url: string, data?: Request) =&amp;gt; Promise&amp;lt;Response&amp;gt;
export type Resolver = &amp;lt;Request, Response&amp;gt;(relationship: Relationship) =&amp;gt; ResolvedRelationship&amp;lt;Request, Response&amp;gt;

export const getHref = (rel: Relationship) =&amp;gt; (typeof rel === "string" ? rel : rel.href)
export const getTitle = (rel: Relationship) =&amp;gt; (typeof rel === "string" ? undefined : rel.title)

export const createResolver = (fetch: JsonFetch) =&amp;gt; &amp;lt;Request, Response&amp;gt;(
  relationship: Relationship
): ResolvedRelationship&amp;lt;Request, Response&amp;gt; =&amp;gt; {

  const apiCall = async (request: Request) =&amp;gt; {
    const rel: { href: Href; method: Method; name?: string } =
      typeof relationship === "string"
        ? {
            href: relationship,
            method: "get"
          }
        : {
            ...relationship,
            method: relationship.method || "get"
          }
    const response = await fetch&amp;lt;Request, Response&amp;gt;(rel.method, rel.href, request)
    return response as Response
  }

  return {
    call: apiCall,
    href: getHref(relationship),
    title: getTitle(relationship)
  }
}

export const createHypermediaModel = &amp;lt;Resource, T&amp;gt;(
  builder: (resource: Resource, resolver: Resolver) =&amp;gt; T
) =&amp;gt; (resolver: Resolver) =&amp;gt; (resource: Resource) =&amp;gt; builder(resource, resolver)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code is written in a functional programming style and functions declared before they are used. Therefore it is usually easier to look at functions starting from the bottom and going up.&lt;/p&gt;

&lt;p&gt;The first function is, therefore, &lt;code&gt;ceateHypermediaModel&lt;/code&gt;, which uses a bit of currying so the resolver and resource can be provided at different times. Dependencies such as Fetch and the Resolver are threaded through the call stack so no global references are needed.&lt;/p&gt;

&lt;p&gt;The other main function is &lt;code&gt;createResolver&lt;/code&gt; which constructs the &lt;code&gt;ResolvedRelationship&lt;/code&gt;. Its main job is to wrap up the call to fetch using the given relationship and the request/response types.&lt;/p&gt;

</description>
      <category>hypermediacontrols</category>
      <category>hypermedia</category>
      <category>rest</category>
      <category>typescript</category>
    </item>
    <item>
      <title>Practical Hypermedia Controls</title>
      <dc:creator>Daniel Little</dc:creator>
      <pubDate>Wed, 08 Jul 2020 00:38:25 +0000</pubDate>
      <link>https://dev.to/daniellittledev/practical-hypermedia-controls-44ci</link>
      <guid>https://dev.to/daniellittledev/practical-hypermedia-controls-44ci</guid>
      <description>&lt;p&gt;A lot has been written about REST but less so when it comes to Hypermedia Controls. I haven't seen too many Hypermedia based APIs out in the wild. I theorize that there are two main reasons for this. First, it is something many people haven't been exposed to, and second, it requires a little more up-front effort in order to get the ball rolling. However, I believe it's an incredibly useful pattern and it's easier to get started than you might think. This post aims to help out with that first problem, exposure. We'll take a look at what Hypermedia Controls are and why they're useful.&lt;/p&gt;

&lt;p&gt;Whatever the reason for the rarity of Hypermedia Controls, what you might commonly see in a REST API instead, is something like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0001"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"daniellittledev"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Daniel Little"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"daniellittle@somewhere"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"canUpdate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"canDeactivate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This JSON object represents a user account. In this system, there are a few simple rules. Only the owner of the resource can update it and only admins can deactivate or activate accounts. This resource uses boolean flags to inform the client what state the object is in and what actions it can perform.&lt;/p&gt;

&lt;p&gt;However, there are some problems with this model.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We can't tell if the current user should be able to activate or deactivate the account.&lt;/li&gt;
&lt;li&gt;We can't tell if the account can be activated, we have to assume it can be because we can't deactivate it.&lt;/li&gt;
&lt;li&gt;We don't know how to update or deactivate an account, we'd need more external information like the URL.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Wouldn't it be nice if all these things were a bit easier to figure out? I think so too!&lt;/p&gt;

&lt;h2&gt;
  
  
  Enter Hypermedia Controls
&lt;/h2&gt;

&lt;p&gt;Hypermedia Controls in REST APIs are all about adding links and actions to a resource instead of needing to interoperate what links and actions are available based on state. Examples of state are boolean flags like above or a status value like &lt;code&gt;ready&lt;/code&gt; or &lt;code&gt;pending&lt;/code&gt;. Here's what the same resource would look like if we added Hypermedia Controls instead.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"daniellittledev"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Daniel Little"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"daniellittle@somewhere"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;

  &lt;/span&gt;&lt;span class="nl"&gt;"links"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"actions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"update"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/account/0001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"method"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"put"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"activate"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/account/0001/activate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"method"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"post"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can clearly see which actions are available. There are two available actions, update and activate, along with the URL and verb needed to make the calls. Instead of the client needing to infer this from the data, the server directly dictates what actions are available. We don't need to assume the client can activate the account if &lt;code&gt;canDeactivate&lt;/code&gt; is &lt;code&gt;false&lt;/code&gt;. There's also no danger of adding conflicting flags. The client can directly show or enable buttons or links directly based on what Hypermedia Controls are present.&lt;/p&gt;

&lt;p&gt;Let's look at our previous problems again, now that we're using Hypermedia.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There is no action for deactivating the account; so the user can't see or perform that action.&lt;/li&gt;
&lt;li&gt;There is an action to activate the account; so the user should see and perform that action.&lt;/li&gt;
&lt;li&gt;We know the URL and method, so the client doesn't need hardcode or build-up any URLs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Much better! This also helps out immensely when debugging or looking at the REST API directly. There's no need for all that extra context to be extracted from the client because it's all there in the resource.&lt;/p&gt;

&lt;p&gt;Also, note that to perform an update you would simply modify the resource as desired and send it right back. You can optionally remove the links and actions, but otherwise, they're typically ignored.&lt;/p&gt;

&lt;p&gt;All this makes the API much easier to reason about and use. But the key benefit is the client no longer needs to interpret any state to figure out what is going on. We're able to keep the knowledge, of who can do what and when, on the server without having to duplicate any logic into the client. And while this example is a fairly trivial one, a few more flags like the ones above or worse, enum states where the client has to decide what buttons are available based on states like &lt;code&gt;Pending&lt;/code&gt;, &lt;code&gt;InProgress&lt;/code&gt; or &lt;code&gt;Completed&lt;/code&gt;, can easily increase complexity and the burden of keeping everything in sync.&lt;/p&gt;

&lt;h2&gt;
  
  
  More Control
&lt;/h2&gt;

&lt;p&gt;We can also do more than just make links and actions available or unavailable. We could also show that an action exists but isn't available. On the UI this could manifest as a visible but disabled button.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"actions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"update"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;disabled:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you'd like things to be a bit more dynamic or server controlled you can also include a title for an action which could be used as the label for a link or button.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"actions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"update"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"href"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/account/0001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"method"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"put"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Update Account"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's really up to you to choose how much information is provided to the client. However, I'd be cautious of adding too much. You might be tempted to include other metadata like field types or validation rules. But the main goal here is to keep duplicate logic out of the client and keep the server in control of application state. Decoupling too much tends to lead to the &lt;a href="https://en.wikipedia.org/wiki/Inner-platform_effect"&gt;Inner Platform Effect&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Client-Side Routing
&lt;/h2&gt;

&lt;p&gt;There's one unexpected question I came across while implementing a Hypermedia based API. Which is how they affect client-side routing. I've found keeping API URLs in sync with the browser URLs to be a good approach. Or to be more accurate, I believe they should be the same URL. If you're coming from a non-hypermedia based API your URLs will most likely have diverged so I'll demonstrate what this looks like in practice.&lt;/p&gt;

&lt;p&gt;The root hypermedia resource is the starting point for the API, it provides all the top level links you'd need to get started.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Request:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;GET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/"&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Response:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"links"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"my-account"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/account/0001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"accounts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/account"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Following a link such as &lt;code&gt;my-account&lt;/code&gt; (which the client knows by name) would update the browsers route to match, eg. &lt;code&gt;/account/0001&lt;/code&gt;. The client-side routing rules mirror the server-side rules to render the relevant components but simply forward the URL directly to the API to fetch a resource. Note that the value here is that the client doesn't have to hardcode, reconstruct or build any URLs.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Request:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;GET&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/account/0001"&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Response:&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"links"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"self"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/account/0001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"home"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Actions are a little different and don't usually represent a route change. I recommend using a get-post-redirect style pattern so that a link (self) or a redirect is used to determine the next URL for the client.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it out
&lt;/h2&gt;

&lt;p&gt;Next time you're building a form with a few actions especially if those actions change under different conditions or states consider using Hypermedia Controls. I hope you enjoyed this article, and if so make sure to keep an eye out for my next post on &lt;a href="https://www.daniellittle.dev/"&gt;Type Safe Hypermedia with Typescript&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>hypermedia</category>
      <category>hypermediacontrols</category>
      <category>rest</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
