DEV Community

E.R. Nurwijayadi
E.R. Nurwijayadi

Posted on • Edited on

Typescript: Playing with Interface

This post was originally posted on my personal blog 😀. The source code example also provided in github, given in that blog.

🕷 Typescript - Small Step into Typed

Goal

Goal: A small step into typescript using custom song script example.

I make this case example, because I want to learn typescript. The task is simply to collect unique tags from records.


Type Basic

Consider start from simple. This is a conventional function in typescript:

const func = function(a: number, b: number): number { return a+b; }

const z: number = func(6,7)
console.log (z)
Enter fullscreen mode Exit fullscreen mode

We can rewrite using ES6's fat arrow, with about the same result, as below code:

const func = (a: number, b: number): number => a+b;

const z: number = func(6,7)
console.log (z)
Enter fullscreen mode Exit fullscreen mode

Or even better with some kind of function signatures, with about the same result, as below code:

type MyFunc = (a: number, b: number) => number;
const func: MyFunc = (a, b) => a + b;

const z: number = func(6,7)
console.log (z)
Enter fullscreen mode Exit fullscreen mode

You can spot the detail. This looks like type signature in functional programming.

Now let's get down to a record case example.


Data Structure: Original in Javascript

Consider a case example of some popular songs from the old decades.

With javascript, I can just write away the records in below form:

const songs  = [
  { title: "Cantaloupe Island",          tags: ["60s", "jazz"] },
  { title: "Let it Be",                  tags: ["60s", "rock"] },
  { title: "Knockin' on Heaven's Door",  tags: ["70s", "rock"] },
  { title: "Emotion",                    tags: ["70s", "pop"] },
  { title: "The River" }
];

export default songs;
Enter fullscreen mode Exit fullscreen mode

Data Structure: Ported to Typescript

With Typescript, you can peacefully append additional interface signature.

interface Song{
  readonly title: string;
  readonly tags?: Array<string>;
}

const songs: Array<Song> = [
  { title: "Cantaloupe Island",
    tags : ["60s", "jazz"] },
  { title: "Let it Be",
    tags : ["60s", "rock"] },
  { title: "Knockin' on Heaven's Door",
    tags : ["70s", "rock"] },
  { title: "Emotion",
    tags : ["70s", "pop"] },
  { title: "The River" }
];

export { Song, songs };
Enter fullscreen mode Exit fullscreen mode

 Data Structure: Ported to Typescript


Procedural: in Javascript

In the old glorious days of Javascript, common approach to solve unique array in records is, by using loop.

let tagSet = new Set();

// using set feature to collect tag names
songs.forEach(function(song) {
  if( "tags" in song ) {
    let tags = song.tags;
    console.log(tags);

    for (const tag of tags) {
      tagSet.add(tag);
    }
  }
});

console.log(tagSet);

// normalize to array
let alltags = [...tagSet];

console.log(alltags);
Enter fullscreen mode Exit fullscreen mode

Well, not so old, this is already using ecmascript 2015.


Functional: in Javascript

These days with ecmascript 2019 we can use flatMap, so the code can be shorter.

import songs from "./songs-data.js";

const unique = array => [... new Set(array)];

const allTags = unique(songs
  .filter(song => song.tags)
  .flatMap(song => song.tags)
);
console.log(allTags );
Enter fullscreen mode Exit fullscreen mode

Functional: in Javascript


Type Interface: in Typescript

With the right code, it is fun to type the interface signature.

import { Song, songs } from "./songs-data";

type   Unique  = (array: Array<string>) => Array<string>;
const  unique  : Unique = (array) => [... new Set(array)];

type  PickTags = (song: Song) => Array<string>;
const pickTags : PickTags = (song) => song.tags!

const allTags: Array<string> = unique(songs
  .filter(  pickTags )
  .flatMap( pickTags )
);
console.log(allTags );
Enter fullscreen mode Exit fullscreen mode

Type Interface: in Typescript

There are details to achieve this in provided link above.
I just want this notes to be short. So I strip out the details here.


Type Interface: with Deno (also Typescript)

However, beware of the difference between ts-node and deno.

All the codes above works well, except we need an adjustment for export import.

This picture should be enough to show the issue

Deno Issue: Type Interface

Export Interface

Instead of ts-node style below:

interface Song{ … }
…
export { Song, songs };
Enter fullscreen mode Exit fullscreen mode

We should use export reserved word as below:

export interface Song{ … }
…
export { songs };
Enter fullscreen mode Exit fullscreen mode

Import

Now you can import as usual, except you must specify, the file extension .ts.

import { Song, songs } from "./songs-data.ts";
Enter fullscreen mode Exit fullscreen mode

The script should works well.
This is the only issue I face so far.
And it has been solved already.


Conclusion

Once I step into this typescript.
It doesn't seems to be scary anymore.
In fact this looks fun.
I should play with language more often.

What do you think?

Top comments (0)