-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
33 changed files
with
1,102 additions
and
395 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,7 +8,17 @@ | |
<language>en</language> | ||
<managingEditor>[email protected] (Sam Stelfox)</managingEditor> | ||
<webMaster>[email protected] (Sam Stelfox)</webMaster> | ||
<lastBuildDate>Wed, 05 Jul 2023 20:11:29 -0400</lastBuildDate><atom:link href="https://stelfox.net/atom.xml" rel="self" type="application/rss+xml" /> | ||
<lastBuildDate>Mon, 31 Jul 2023 07:38:29 -0400</lastBuildDate><atom:link href="https://stelfox.net/atom.xml" rel="self" type="application/rss+xml" /> | ||
<item> | ||
<title>Rust/TypeScript Type Synchronization</title> | ||
<link>https://stelfox.net/blog/2023/07/rust/typescript-type-synchronization/</link> | ||
<pubDate>Mon, 31 Jul 2023 07:38:29 -0400</pubDate> | ||
<author>[email protected] (Sam Stelfox)</author> | ||
<guid>https://stelfox.net/blog/2023/07/rust/typescript-type-synchronization/</guid> | ||
<description>I&rsquo;ve been looking at integrating a React front-end with a Rust API server and one of the ongoing annoyances I encountered was keeping API types in sync with each other. I found a couple of options, the smallest and simplest one I liked was tsync. | ||
I try to keep my dependency lists small, and this crate is a bit of an odd duck as it is only really doing work as a build dependency.</description> | ||
</item> | ||
|
||
<item> | ||
<title>Dealing with Branch Protection Rules Using GitHub's Settings App</title> | ||
<link>https://stelfox.net/blog/2023/07/dealing-with-branch-protection-rules-using-githubs-settings-app/</link> | ||
|
@@ -98,15 +108,5 @@ The most common fix was when people had three button mouse emulation enabled (a | |
Every now and then the container would crash, it would automatically recover fast enough no alarms were lost and the clients would just resend their requests.</description> | ||
</item> | ||
|
||
<item> | ||
<title>Fixing Dark Input Boxes in Firefox</title> | ||
<link>https://stelfox.net/blog/2019/04/fixing-dark-input-boxes-in-firefox/</link> | ||
<pubDate>Sat, 13 Apr 2019 11:53:22 -0400</pubDate> | ||
<author>[email protected] (Sam Stelfox)</author> | ||
<guid>https://stelfox.net/blog/2019/04/fixing-dark-input-boxes-in-firefox/</guid> | ||
<description>I recently began trying out Cinnamon as my desktop environment and I&rsquo;ve been thoroughly enjoying it. The only issue I was having was occasionally a page&rsquo;s form input fields would have a dark background while still having dark text making it impossible to read, and very difficult to write. | ||
It wasn&rsquo;t happening everywhere, and I couldn&rsquo;t track down what about a website would cause the issue. Most prominently for me was when this showed up in AWS&rsquo;s interface.</description> | ||
</item> | ||
|
||
</channel> | ||
</rss> |
240 changes: 240 additions & 0 deletions
240
blog/2023/07/rust/typescript-type-synchronization/index.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,240 @@ | ||
<!DOCTYPE html> | ||
<html lang="en"> | ||
<head> | ||
<meta charset="UTF-8"> | ||
<meta http-equiv="X-UA-Compatible" content="ie=edge"> | ||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> | ||
<meta name="author" content="[email protected] Sam Stelfox "> | ||
<meta name="description" content="I&rsquo;ve been looking at integrating a React front-end with a Rust API server and one of the ongoing annoyances I encountered was keeping API types in sync with each other. I found a couple of options, the smallest and simplest one I liked was tsync. | ||
I try to keep my dependency lists small, and this crate is a bit of an odd duck as it is only really doing work as a build dependency." /> | ||
<meta name="keywords" content="blog, programming, linux, systems, personal, development, rust, typescript, web-development" /> | ||
<meta name="robots" content="noodp" /> | ||
<meta name="theme-color" content="" /> | ||
<link rel="canonical" href="https://stelfox.net/blog/2023/07/rust/typescript-type-synchronization/" /> | ||
|
||
|
||
<title> | ||
|
||
Rust/TypeScript Type Synchronization :: Sam Stelfox | ||
|
||
</title> | ||
|
||
|
||
|
||
|
||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/flag-icon-css/3.5.0/css/flag-icon.min.css" integrity="sha512-Cv93isQdFwaKBV+Z4X8kaVBYWHST58Xb/jVOcV9aRsGSArZsgAnFIhMpDoMDcFNoUtday1hdjn0nGp3+KZyyFw==" crossorigin="anonymous" referrerpolicy="no-referrer" /> | ||
|
||
|
||
|
||
<link rel="stylesheet" href="/main.2a064c455b0ecbd6b1481b3bf9df2441e95838691022f40a5338c2cb1244f075.css" integrity="sha256-KgZMRVsOy9axSBs7+d8kQelYOGkQIvQKUzjCyxJE8HU="> | ||
|
||
|
||
|
||
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png"> | ||
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png"> | ||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png"> | ||
<link rel="manifest" href="/site.webmanifest"> | ||
<link rel="mask-icon" href="/safari-pinned-tab.svg" color=""> | ||
<link rel="shortcut icon" href="/favicon.ico"> | ||
<meta name="msapplication-TileColor" content=""> | ||
|
||
|
||
<meta itemprop="name" content="Rust/TypeScript Type Synchronization"> | ||
<meta itemprop="description" content="I’ve been looking at integrating a React front-end with a Rust API server and one of the ongoing annoyances I encountered was keeping API types in sync with each other. I found a couple of options, the smallest and simplest one I liked was tsync. | ||
I try to keep my dependency lists small, and this crate is a bit of an odd duck as it is only really doing work as a build dependency."><meta itemprop="datePublished" content="2023-07-31T07:38:29-04:00" /> | ||
<meta itemprop="dateModified" content="2023-07-31T07:38:29-04:00" /> | ||
<meta itemprop="wordCount" content="391"> | ||
<meta itemprop="keywords" content="development,rust,typescript,web-development," /> | ||
<meta name="twitter:card" content="summary"/> | ||
<meta name="twitter:title" content="Rust/TypeScript Type Synchronization"/> | ||
<meta name="twitter:description" content="I’ve been looking at integrating a React front-end with a Rust API server and one of the ongoing annoyances I encountered was keeping API types in sync with each other. I found a couple of options, the smallest and simplest one I liked was tsync. | ||
I try to keep my dependency lists small, and this crate is a bit of an odd duck as it is only really doing work as a build dependency."/> | ||
|
||
|
||
|
||
<meta property="og:title" content="Rust/TypeScript Type Synchronization" /> | ||
<meta property="og:description" content="I’ve been looking at integrating a React front-end with a Rust API server and one of the ongoing annoyances I encountered was keeping API types in sync with each other. I found a couple of options, the smallest and simplest one I liked was tsync. | ||
I try to keep my dependency lists small, and this crate is a bit of an odd duck as it is only really doing work as a build dependency." /> | ||
<meta property="og:type" content="article" /> | ||
<meta property="og:url" content="https://stelfox.net/blog/2023/07/rust/typescript-type-synchronization/" /><meta property="article:section" content="blog" /> | ||
<meta property="article:published_time" content="2023-07-31T07:38:29-04:00" /> | ||
<meta property="article:modified_time" content="2023-07-31T07:38:29-04:00" /> | ||
|
||
|
||
|
||
|
||
|
||
|
||
<meta property="article:published_time" content="2023-07-31 07:38:29 -0400 EDT" /> | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
</head> | ||
|
||
|
||
<body> | ||
|
||
|
||
<div class="container"> | ||
<header class="header"> | ||
<span class="header__inner"> | ||
<a href="/" style="text-decoration: none;"> | ||
<div class="logo"> | ||
|
||
<span class="logo__mark">></span> | ||
<span class="logo__text "> | ||
./Sam_Stelfox.sh</span> | ||
<span class="logo__cursor" style= | ||
" | ||
"> | ||
</span> | ||
|
||
</div> | ||
</a> | ||
|
||
|
||
<span class="header__right"> | ||
|
||
<nav class="menu"> | ||
<ul class="menu__inner"><li><a href="/about/">About</a></li><li><a href="/blog/">Blog Posts</a></li><li><a href="/notes/">Various Notes</a></li> | ||
</ul> | ||
</nav> | ||
|
||
<span class="menu-trigger"> | ||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> | ||
<path d="M0 0h24v24H0z" fill="none"/> | ||
<path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"/> | ||
</svg> | ||
</span> | ||
|
||
</span> | ||
</span> | ||
</header> | ||
|
||
|
||
<div class="content"> | ||
|
||
<main class="post"> | ||
|
||
<div class="post-info"> | ||
|
||
</p> | ||
</div> | ||
|
||
<article> | ||
<h2 class="post-title"><a href="https://stelfox.net/blog/2023/07/rust/typescript-type-synchronization/">Rust/TypeScript Type Synchronization</a></h2> | ||
|
||
|
||
|
||
|
||
|
||
<div class="post-content"> | ||
<p>I’ve been looking at integrating a React front-end with a Rust API server and | ||
one of the ongoing annoyances I encountered was keeping API types in sync with | ||
each other. I found a couple of options, the smallest and simplest one I liked | ||
was <a href="https://crates.io/crates/tsync">tsync</a>.</p> | ||
<p>I try to keep my dependency lists small, and this crate is a bit of an odd duck | ||
as it is only really doing work as a build dependency. If you look at the macro | ||
definition it doesn’t do anthing to the TokenStream its passed, making it a | ||
no-op attribute. It’s just used during this special pass done during the build | ||
step.</p> | ||
<p>Since its a no-op during regular compilation, it’d be nice if the tsync code | ||
wasn’t compiled or linked in to the final application. The nature of attribute | ||
macros means they cause an error without the definition, and since Rust | ||
requires attribute macros be defined in a special type of crate they tend to be | ||
fully decoupled from the main crate which is also the case here.</p> | ||
<p>The workaround uses the macro crate directly in normal builds while only using | ||
the full version during the build step. First we need to add both crates as | ||
direct dependencies:</p> | ||
<div class="highlight"><pre tabindex="0" style="color:#c9d1d9;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>cargo add --build tsync@^1 | ||
</span></span><span style="display:flex;"><span>cargo add tsync-macro@^0.1 | ||
</span></span></code></pre></div><p>The versions are correct, the tsync-macro crate is independently versioned and | ||
hasn’t been bumped.</p> | ||
<p>Now during builds we want our source scanned for the attribute, and a | ||
typescript file generated with all the appropriate types. You can create or | ||
edit an existing <code>build.rs</code> file with the following content to do so:</p> | ||
<div class="highlight"><pre tabindex="0" style="color:#c9d1d9;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span>use std::path::PathBuf; | ||
</span></span><span style="display:flex;"><span> | ||
</span></span><span style="display:flex;"><span>const TYPESCRIPT_OUTPUT: &str = "frontend/src/rust_types.d.ts"; | ||
</span></span><span style="display:flex;"><span> | ||
</span></span><span style="display:flex;"><span>fn generate_typescript_definitions() { | ||
</span></span><span style="display:flex;"><span> let dir = env!("CARGO_MANIFEST_DIR"); | ||
</span></span><span style="display:flex;"><span> | ||
</span></span><span style="display:flex;"><span> let inputs = vec![PathBuf::from(dir)]; | ||
</span></span><span style="display:flex;"><span> let output = PathBuf::from_iter([dir, TYPESCRIPT_OUTPUT]); | ||
</span></span><span style="display:flex;"><span> | ||
</span></span><span style="display:flex;"><span> tsync::generate_typescript_defs(inputs, output, false); | ||
</span></span><span style="display:flex;"><span>} | ||
</span></span><span style="display:flex;"><span> | ||
</span></span><span style="display:flex;"><span>fn main() { | ||
</span></span><span style="display:flex;"><span> generate_typescript_definitions(); | ||
</span></span><span style="display:flex;"><span>} | ||
</span></span></code></pre></div><p>My TypeScript/React frontend project lives inside my Rust project in a | ||
directory called “frontend”. If you’d like the file to be saved elsewhere, edit | ||
the value of the <code>TYPESCRIPT_OUTPUT</code> variable.</p> | ||
<p>Using the attribute is pretty straight-forward but slightly different than what | ||
the crate’s documentation tell you to do:</p> | ||
<div class="highlight"><pre tabindex="0" style="color:#c9d1d9;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-rust" data-lang="rust"><span style="display:flex;"><span><span style="color:#ff7b72">use</span><span style="color:#6e7681"> </span>tsync_macro::tsync;<span style="color:#6e7681"> | ||
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681"> | ||
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681"></span><span style="color:#8b949e;font-weight:bold;font-style:italic">#[tsync]</span><span style="color:#6e7681"> | ||
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681"></span><span style="color:#ff7b72">pub</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">type</span> <span style="color:#f0883e;font-weight:bold">Timestamp</span><span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">=</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">usize</span>;<span style="color:#6e7681"> | ||
</span></span></span></code></pre></div><p>Or just inline:</p> | ||
<div class="highlight"><pre tabindex="0" style="color:#c9d1d9;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-rust" data-lang="rust"><span style="display:flex;"><span><span style="color:#8b949e;font-weight:bold;font-style:italic">#[tsync_macro::tsync]</span><span style="color:#6e7681"> | ||
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681"></span><span style="color:#ff7b72">type</span> <span style="color:#f0883e;font-weight:bold">Timestamp</span><span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">=</span><span style="color:#6e7681"> </span><span style="color:#ff7b72">usize</span>;<span style="color:#6e7681"> | ||
</span></span></span></code></pre></div><p>Run a build and you should see the file <code>frontend/src/rust_types.d.ts</code> get | ||
created with the following contents:</p> | ||
<div class="highlight"><pre tabindex="0" style="color:#c9d1d9;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-ts" data-lang="ts"><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic">/* This file is generated and managed by tsync */</span> | ||
</span></span><span style="display:flex;"><span> | ||
</span></span><span style="display:flex;"><span><span style="color:#ff7b72">type</span> Timestamp <span style="color:#ff7b72;font-weight:bold">=</span> <span style="color:#ff7b72">number</span> | ||
</span></span></code></pre></div><p>Voila! Effortless type synchronization.</p> | ||
|
||
</div> | ||
</article> | ||
|
||
<hr /> | ||
|
||
<div class="post-info"> | ||
|
||
<p> | ||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-tag meta-icon"><path d="M20.59 13.41l-7.17 7.17a2 2 0 0 1-2.83 0L2 12V2h10l8.59 8.59a2 2 0 0 1 0 2.82z"></path><line x1="7" y1="7" x2="7" y2="7"></line></svg> | ||
|
||
<span class="tag"><a href="https://stelfox.net/tags/development/">development</a></span> | ||
<span class="tag"><a href="https://stelfox.net/tags/rust/">rust</a></span> | ||
<span class="tag"><a href="https://stelfox.net/tags/typescript/">typescript</a></span> | ||
<span class="tag"><a href="https://stelfox.net/tags/web-development/">web-development</a></span> | ||
|
||
</p> | ||
|
||
|
||
</div> | ||
</main> | ||
|
||
</div> | ||
|
||
|
||
<footer class="footer"> | ||
|
||
|
||
</footer> | ||
|
||
|
||
</div> | ||
|
||
|
||
|
||
|
||
|
||
<script type="text/javascript" src="/bundle.min.c90b8161416b87c69a8e02683b54ddd6edb90aea699648bf655e6cbc45b419b8e465d196e715772463dba35a6faf5decb2eb247480d38680484d54645b434570.js" integrity="sha512-yQuBYUFrh8aajgJoO1Td1u25Cupplki/ZV5svEW0GbjkZdGW5xV3JGPbo1pvr13ssuskdIDThoBITVRkW0NFcA=="></script> | ||
|
||
|
||
|
||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,7 +8,17 @@ | |
<language>en</language> | ||
<managingEditor>[email protected] (Sam Stelfox)</managingEditor> | ||
<webMaster>[email protected] (Sam Stelfox)</webMaster> | ||
<lastBuildDate>Wed, 05 Jul 2023 20:11:29 -0400</lastBuildDate><atom:link href="https://stelfox.net/blog/atom.xml" rel="self" type="application/rss+xml" /> | ||
<lastBuildDate>Mon, 31 Jul 2023 07:38:29 -0400</lastBuildDate><atom:link href="https://stelfox.net/blog/atom.xml" rel="self" type="application/rss+xml" /> | ||
<item> | ||
<title>Rust/TypeScript Type Synchronization</title> | ||
<link>https://stelfox.net/blog/2023/07/rust/typescript-type-synchronization/</link> | ||
<pubDate>Mon, 31 Jul 2023 07:38:29 -0400</pubDate> | ||
<author>[email protected] (Sam Stelfox)</author> | ||
<guid>https://stelfox.net/blog/2023/07/rust/typescript-type-synchronization/</guid> | ||
<description>I&rsquo;ve been looking at integrating a React front-end with a Rust API server and one of the ongoing annoyances I encountered was keeping API types in sync with each other. I found a couple of options, the smallest and simplest one I liked was tsync. | ||
I try to keep my dependency lists small, and this crate is a bit of an odd duck as it is only really doing work as a build dependency.</description> | ||
</item> | ||
|
||
<item> | ||
<title>Dealing with Branch Protection Rules Using GitHub's Settings App</title> | ||
<link>https://stelfox.net/blog/2023/07/dealing-with-branch-protection-rules-using-githubs-settings-app/</link> | ||
|
@@ -98,15 +108,5 @@ The most common fix was when people had three button mouse emulation enabled (a | |
Every now and then the container would crash, it would automatically recover fast enough no alarms were lost and the clients would just resend their requests.</description> | ||
</item> | ||
|
||
<item> | ||
<title>Fixing Dark Input Boxes in Firefox</title> | ||
<link>https://stelfox.net/blog/2019/04/fixing-dark-input-boxes-in-firefox/</link> | ||
<pubDate>Sat, 13 Apr 2019 11:53:22 -0400</pubDate> | ||
<author>[email protected] (Sam Stelfox)</author> | ||
<guid>https://stelfox.net/blog/2019/04/fixing-dark-input-boxes-in-firefox/</guid> | ||
<description>I recently began trying out Cinnamon as my desktop environment and I&rsquo;ve been thoroughly enjoying it. The only issue I was having was occasionally a page&rsquo;s form input fields would have a dark background while still having dark text making it impossible to read, and very difficult to write. | ||
It wasn&rsquo;t happening everywhere, and I couldn&rsquo;t track down what about a website would cause the issue. Most prominently for me was when this showed up in AWS&rsquo;s interface.</description> | ||
</item> | ||
|
||
</channel> | ||
</rss> |
Oops, something went wrong.