<?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: Chris Mytton</title>
    <description>The latest articles on DEV Community by Chris Mytton (@chrismytton).</description>
    <link>https://dev.to/chrismytton</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%2F105816%2F5fe5e07b-633b-444f-94ab-b63b7c40312e.jpg</url>
      <title>DEV Community: Chris Mytton</title>
      <link>https://dev.to/chrismytton</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/chrismytton"/>
    <language>en</language>
    <item>
      <title>Canvas art with TypeScript</title>
      <dc:creator>Chris Mytton</dc:creator>
      <pubDate>Fri, 03 Jul 2020 14:34:30 +0000</pubDate>
      <link>https://dev.to/chrismytton/canvas-art-with-typescript-2d82</link>
      <guid>https://dev.to/chrismytton/canvas-art-with-typescript-2d82</guid>
      <description>&lt;p&gt;I ported a JavaScript "random art generator" I created a few years ago over to TypeScript. This post contains some notes from the process.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;See the project: &lt;a href="https://www.chrismytton.uk/art/"&gt;www.chrismytton.uk/art&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Check out the code: &lt;a href="https://github.com/chrismytton/art/blob/1f34e99d121f2c7dd698eb8c9d45da1e9b7f450c/src/random.ts"&gt;chrismytton/art on GitHub&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;I've been learning TypeScript recently. As part of that I wanted to dig out some of my old JavaScript projects and port them to TypeScript. I find porting code to a new language is a good way to learn.&lt;/p&gt;

&lt;p&gt;I found an old project that I created in 2014 which uses JavaScript and the Canvas API to create random pieces of art which change on every page load. The code itself is fairly straightforward, so it seemed like a good candidate for porting to TypeScript.&lt;/p&gt;

&lt;h2&gt;
  
  
  Classes in TypeScript
&lt;/h2&gt;

&lt;p&gt;TypeScript classes build on &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes"&gt;ES6 classes&lt;/a&gt;. The major difference is that in TypeScript you need to explicitly declare the types of properties you're expecting on the class.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;CanvasPainting&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;viewport&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HTMLCanvasElement&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CanvasRenderingContext2D&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you try to use &lt;code&gt;this.viewport&lt;/code&gt; without declaring the property TypeScript will tell you:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Property 'viewport' does not exist on type 'CanvasPainting'.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I find having these properties explicitly defined actually makes it easier to figure out what the class might be doing internally. They provide useful documentation about what kind of data you can expect to find in each property.&lt;/p&gt;

&lt;h2&gt;
  
  
  Index signatures
&lt;/h2&gt;

&lt;p&gt;This is something I struggled with for a while. I was trying to dynamically call methods on my &lt;code&gt;Shapes&lt;/code&gt; class using &lt;code&gt;this[shape]&lt;/code&gt;, but TypeScript was giving this warning:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'Shapes'.&lt;/p&gt;

&lt;p&gt;No index signature with a parameter of type 'string' was found on type 'Shapes'.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After reading various bits of the TypeScript documentation and some Stack Overflow answers I eventually figured out that I needed to define an index signature on my shapes class. This tells TypeScript what can be used to index this class, and what the indexing might return.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Shapes&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;CanvasPainting&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This tells TypeScript that you can index this class with a string, and it will return &lt;em&gt;something&lt;/em&gt;. There might be a way to avoid using &lt;code&gt;any&lt;/code&gt; here, but I haven't figured that out yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dealing with null values
&lt;/h2&gt;

&lt;p&gt;TypeScript knows which methods can return &lt;code&gt;null&lt;/code&gt; and will make you deal with those cases. If you try to call a method on a value that might be null then TypeScript will give you a warning.&lt;/p&gt;

&lt;p&gt;You can avoid this warning by explicitly checking for &lt;code&gt;null&lt;/code&gt; before using the value.&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;CanvasPainting&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;viewport&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HTMLCanvasElement&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CanvasRenderingContext2D&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;viewport&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HTMLCanvasElement&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;viewport&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;viewport&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;viewport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2d&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// getContext can return null, so check for that case.&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;getContext('2d') failed&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ctx&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Without this check for &lt;code&gt;null&lt;/code&gt; TypeScript warns you that &lt;code&gt;Type 'null' is not assignable to type 'CanvasRenderingContext2D'.&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It's easy to forget to check for &lt;code&gt;null&lt;/code&gt; when writing JavaScript. TypeScript protects you from this class of error at the compile stage.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;I really like what I've seen so far with TypeScript. Working on little projects like this is a great way to get some experience with new tools.&lt;/p&gt;

&lt;p&gt;I'd forgotten all about this fun little art project. It's nice to have given it a bit of polish and released it into the world, rather than it gathering dust on my hard drive.&lt;/p&gt;

&lt;p&gt;See the project: &lt;a href="https://www.chrismytton.uk/art/"&gt;www.chrismytton.uk/art&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Check out the code: &lt;a href="https://github.com/chrismytton/art/blob/1f34e99d121f2c7dd698eb8c9d45da1e9b7f450c/src/random.ts"&gt;chrismytton/art on GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>typescript</category>
      <category>art</category>
    </item>
  </channel>
</rss>
