DEV Community

E.R. Nurwijayadi
E.R. Nurwijayadi

Posted on β€’ Edited on

1 1

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)

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up