Showing posts with label TypeScript. Show all posts
Showing posts with label TypeScript. Show all posts

Friday, June 11, 2021

Understanding the Magic behind Utility Types in TypeScript

This post will be the conlcuding post in the Introduction to Advanced Types in TypeScript series. It looks at some of the utility Types in TypeScript, explain how it works while pointing out the features within the TypeScript type system that makes it possible.

Why TypeScript?

TypeScript comes with a powerful and expressive type system. Its expressiveness makes it a joy to work with while its powerful features makes it possible to build, and scale large codebases by providing type safety.

One of the ways TypeScript brings about type safety is by providing developers the tool to manipulate types in ways that encode constraints within the type system. This then ensures that code that could lead to runtime exception do not compile, making it possible to catch errors during development time and not in production. One of such tools TypeScript provides for this are Utility Types.

Utility Types are a set of Generic Types that come natively within TypeScript that makes it possible to transform one type into another. This sort of type transformation is useful because it makes it possible to take exiting types, and apply modifications to it which would ensure the enforcement of certain constraints.

In this post, we would look at 2 of such Utility type and how they could be used to provide more type safety. After that, we would take a step back to understand some of the other TypeScript features that come together to make Utility Types possible. Armed with this knowledge, we will then demystify Utility types by taking a peek under the hood of the 2 Utility types in focus to see how they are implemented.


Monday, June 07, 2021

First impressions with Deno from building PlanetTypeScript.com

PlanetTypeScript.com is a content aggregator for all things TypeScript. It regularly polls RSS feeds for TypeScript related content, which it then list on the site, send out as a tweet via @planetypescript, and also as a weekly digest to subscribers.

Back when I used to write a lot of Java-related content on this blog, I found out that my blog ended up on www.topjavablogs.com/, which is a site that aggregates Java contents. So when I decided to play around with Deno, I thought a nice little idea would be to build something similar to topjavablogs.com, but for TypeScript. And that is how PlanetTypescript.com was born.

In this post, I will share some of my first impressions with Deno. The things I enjoyed and the bits I found inconvenient. Let's start with the cool stuff.


Friday, May 28, 2021

3 Ways to Name Types in Typescript

TypeScript type's system is structural and hence, it allows for the easy creation of types based on the shape of data. These types can be created and used without having a name. For example:

let john: {name: string, age: number} = { 
  name: "John Doe", 
  age: 30
}

Where {name: string, age: number} is the type defined.

But there is a problem with using the type definition this way. If we want to create another person and annotate another variable with the type, we would need to repeat ourselves:

let john: {name: string, age: number} = {
  name: "John Doe", 
  age: 30
}

let jane: {name: string, age: number} = {
   name: "Jane Doe", 
   age: 45
}

This is not dry.


Sunday, May 09, 2021

ip-num v1.3.2 has been released

ip-num is A TypeScript/JavaScript library for working with ASN, IPv4, and IPv6 numbers. It provides representations of these internet protocol numbers with the ability to perform various IP related operations like parsing, validating etc, on them.

A new version of ip-num, version 1.3.2 is now available.

This release contains one new feature and a bug fix.

Add method to split range into smaller ranges of certain size

In previous versions of ip-num, it was possible to take IP ranges with prefix less than /32 and split them into two. For example:

import {IPv4CidrRange} from "ip-num/IPRange";
import {IPv4Prefix} from "ip-num/Prefix";

let ipv4CidrRange = IPv4CidrRange.fromCidr("192.168.208.0/24");
let splitRanges: Array<IPv4CidrRange> = ipv4CidrRange.split();

// console logs:
// 192.168.208.0/25
// 192.168.208.128/25

splitRanges.forEach(range => console.log(range.toCidrString()))

But what if one needs to take an IP range and instead of just splitting into two, there is the requirement to split into a number of ranges with a specified prefix? Well, that is now possible with the addition of splitInto method:

import {IPv4CidrRange} from "ip-num/IPRange";
import {IPv4Prefix} from "ip-num/Prefix";

let ipv4CidrRange = IPv4CidrRange.fromCidr("192.168.208.0/24");
let splitRanges: Array<IPv4CidrRange> = 
ipv4CidrRange.splitInto(IPv4Prefix.fromNumber(26));

// console logs:
// 192.168.208.0/26
// 192.168.208.64/26
// 192.168.208.128/26
// 192.168.208.192/26

splitRanges.forEach(range => console.log(range.toCidrString()))

RangedSet.isCidrAble() incorrect results

Previous versions of ip-num failed to properly report that a string representing a single IP can be represented in the CIDR notation. This has now been fixed:

import {RangedSet} from "ip-num/IPRange";

let rangedSet= RangedSet.fromRangeString("1.2.3.4-1.2.3.4");

// now returns true
console.log(rangedSet.isCidrAble())

As always, ip-num is just an npm install or npm upgrade away.

Feel free to open an issue to discuss a feature or to report a bug.


Sunday, April 25, 2021

Mapped Types in Typescript

This post will explore Mapped Types, another advanced feature of the Typescript type system. It is part of the Introduction to Advanced Types in TypeScript series.

A useful mental model to have when approaching some of the advanced type system features of Typescript is to view them as a mechanism for constructing other types from existing types. This view is spot on when it comes to mapped types as they are a mechanism that Typescript provides by constructing new types by mapping existing types into new ones.

This post would show how this looks like. It would be as beginner-friendly as possible, but having some knowledge of GenericsUnion Types and Literal types in Typescript would be a plus.

To kickstart we take a quick again, at the keyof Operator, as it is essential to the workings of Mapped Types.


Tuesday, April 06, 2021

Conditional Types in Typescript

This post is about conditional types in typescript, which happens to be an interesting and powerful feature of the typescript's type system. It is part of the Introduction to Advance Types in TypeScript series.

Conditional types can be seen as a mechanism that allows us to perform ternary operations on types. 

Normally, ternary operations work with values, for example:

resulting value == true ? value A : value B
let value = 10
const isEven = value % 2 == 0 ? true : false
Conditional types gives us the ability to perform similar operation on types. Where we get a type out of two possibility, depending on the outcome of a check. 


Saturday, April 03, 2021

any, unknown and never types in Typescript

This post will be a quick overview of three interesting types in Typescript: any, unknown, and never with the aim of quickly explaining what they are, and when to use them. It is part of the Introduction to Advance Types in TypeScript series.  

To start with, it is a good mental model to view Types from the perspective of set theory. This idea is fully explored in Union and Intersection Types in TypeScript, but for a quick summary, the idea is simple. When types are created, see it as similar to defining a Set. And what do sets contain? they contain objects. The next thing is to see values as objects that belongs to a set. A value defined to be part of a set, would not be allowed in a different set which it does not belong in or overlap with. 


Friday, April 02, 2021

Tuple Types in TypeScript

In this post, we would be looking at tuple types in TypeScript. It will also touch on generic rest parameters and variadic tuple types which are two of the advanced parts of tuple types. 


Saturday, February 27, 2021

Introduction to Index Types in TypeScript

This post will look at Index Types in TypeScript. It will go over what they are and also touch on two type-operators related to them. These type operators are the index type query operator and indexed access operators. 

This post is part of the Introduction to Advanced Types in TypeScript series. To better understand, it requires having some familiarity with Union Types, Generics, and Literal types. These are topics that have already been covered in the series.


Tuesday, February 16, 2021

Overview of Indexable Types In TypeScript

This blog post will look at Indexable Types. It is part of the Introduction to Advanced Types in TypeScript series.

In JavaScript, there are values, from which additional values can be retrieved via an index. A natural example of such a value is an Array: For example, given the following array:

const primaryColors =  ["red", "green", "blue"]

The value primaryColors is an array value, and its individual content can be accessed by providing an index of type number:

console.log(primaryColors[0])
console.log(primaryColors[1])
console.log(primaryColors[2])


Sunday, February 07, 2021

Using Literal and Template Literal Types in TypeScript

This blog post will look at some of the use cases of literal and template literal types in TypeScript. It is a continuation of Literal and Template Literal Types, which introduces the language feature and it is a part of the Introduction to Advanced Types in TypeScript series.

This post will look at the following use cases:

  1. Compile time spell checker
  2. Alternative to enum
  3. Discriminated Union Pattern
  4. Stricter Type Constraints and Type Level Computation

Monday, February 01, 2021

Literal and Template Literal Types

This blog post will look at Literal and Template Literal Types. It is part of the Introduction to Advanced Types in TypeScript series.

In the post, Union and Intersection Types in TypeScript, the idea of viewing types with the perspective of Set theory was introduced. The key idea is to see types more or less as sets, and values of a type as elements that belong to a set. If this idea of viewing types from the perspective of Set theory is new to you, then I’ll advise to take a pause and read Union and Intersection Types in TypeScript before continuing with the rest of the post, because it is a useful perspective to understand literal types.


Monday, January 18, 2021

Union and Intersection Types in TypeScript

This blog post will look at Union and Intersection types in TypeScript. It is part of the Introduction to Advance Types in TypeScript series.

Union and Intersection types are useful features of TypeScript. But they can come across as a bit strange, especially to developers coming from more traditional languages like Java, C#, etc. Hence in this post, I will first start with a background section. This will help in developing the fundamental perspective needed to understand and appreciate union and intersection types in TypeScript.  


Wednesday, January 13, 2021

Generic Constraints, Generic Methods, and Generic Factories in TypeScript

In Introduction to Generics in TypeScript the idea of Generics was introduced. It was shown how Generics provide a mechanism for having a balance between writing code that is flexible enough to apply to a broad range of types but not too flexible that type safety is lost. 

This post will be a short one that builds on that and shows a couple of extra things that can be achieved when using Generics in TypeScript. Three things will be shown in this post: Generic Constraints, Generic Methods, and Generic Factories


Monday, January 11, 2021

Introduction to Generics in TypeScript

Generics provides a mechanism for writing code that is flexible enough to apply to a broad range of types but not too flexible that type safety is lost. 

What exactly does the above statement mean?

To demonstrate what it means, we will define a class and a function that makes use of Generics. The generic class will be an implementation of a List, which only allows adding and retrieving an item and the generic function will be the identity function

Both the List data structure and the Identity function are good examples because they are straightforward enough to allow for easy demonstration of the Generics concepts.

Let’s start with List.


Introduction to Advanced Types in TypeScript

This is the start of a series of posts where I take a look at aspects of TypeScript's type system that can be referred to as "Advanced".  See this as an exploration of TypeScript’s type system past Classes and Interfaces.

A good mental model to have when exploring the advanced part of TypeScript type system is to see it as a more sophisticated mechanism for creating types. 

The normal, non-advanced ways of creating types in TypeScript involve using features of the language like type aliasclass and interface

For example these: 

interface IPerson {
  name: string
  age: number
}

type TPerson = {
  name: string
  age: number
}

class CPerson {
  constructor(private name:string, private age: number) {}
  
  getName() {
    return this.name;
  }

  getAge() {
    return this.name;
  }
}

With the advanced type features, types can be constructed directly or indirectly based on other existing types. How exactly this is done, will be the subject of this series of posts.

The posts in the series include:


Sunday, January 10, 2021

How to apply type annotations to functions in TypeScript

This post explores the various ways of ascribing functions with type annotations in TypeScript. To fully appreciate the various ways of ascribing type annotations to functions, we would first take a quick look at the various ways functions can be defined in JavaScript. Once that is done, we then look at how to bring TypeScript's static type annotation into the picture. 

There are mainly two ways of defining functions in JavaScript. Namely: 
  • Function expressions 
  • Function declarations. 
Let’s quickly go over how these two work.


Friday, June 28, 2019

Generators and Iterators in JavaScript

This post concludes the series Symbols, Iterables, Iterators and Generators in JavaScript. It would be a whirlwind tour of generator functions in JavaScript and how they can be put to use when defining Iterators.

It is a direct follow up of Typing Iterables and Iterators with TypeScript and it would take the Iterator defined in the post, and improve it by making use of generator functions.

Basically, it will show how we can go from a verbose implementation that does not make use of generator functions:

class MakeRange {
    private _first: number;
    private _last: number
    constructor(first, last) {
     this._first = first;
     this._last = last;
   }
 
    [Symbol.iterator]() {
        return {
            next: () => {
                  if (this._first < this._last) {
                      return {value: this._first++, done: false}
                  } else {
                      return {value: undefined, done: true}
                 }
           }
       }
   }
 }

Into a more terse and clearer implementation that makes use of generator functions:

class MakeRange {
    private _first: number
    private _last: number

    constructor(first, last) {
     this._first = first;
     this._last = last;
    }

    *[Symbol.iterator]() {
        while (this._first < this._last) {
            yield this._first++
       }
   }
}

This post contains the following sections:

Meaning, we are going to first look at what generator functions are, then we see the various syntaxes for creating them, and finally we bring them to use in simplifying how we define iterables and iterators.

Let's get started.


Sunday, June 23, 2019

Typing Iterables and Iterators with TypeScript

In this post, we are going to do a quick exploration of how TypeScript allows for compile time guarantees when working with the iteration protocol in JavaScript.

It is part of a series about Symbols, Iterables, Iterators and Generators in JavaScript, and a direct follow up of a previous post: Iteration Protocol And Configuring The TypeScript Compiler which was about the necessary compiler configurations needed to be able to work with iterables and iterators from TypeScript.

This post will then take things from there, and show how to add types to Iterables and Iterators in other to get compile time checking working.


Saturday, June 22, 2019

Iteration Protocol And Configuring The TypeScript Compiler

This post is part of the series of post on Symbols, Iterables, Iterators and Generators. It is part of various blog posts, where I penned down some of the things I learnt about TypeScript and JavaScript, while working on ip-num: A TypeScript library for working with ASN, IPv4, and IPv6 numbers.

This post would be about how to configure the TypeScript compiler in other to be able to work with the iteration protocol.

TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. I have heard it described in some quarters as "JavaScript that scales".

The core feature of TypeScript that allows it to be described as such is the static guarantees and compile time safety it introduces, which allows invariants and structure about code base to be validated and checked for correctness at compile time.

In previous posts in this series, I have looked at Symbols In JavaScript and Iterables and Iterators in JavaScript. One of the things that stands out in these posts, is the requirement to have objects that have certain structure or adhere to stipulated protocols in other to be considered as Iterables or Iterators. Formally, these sets of requirement are known as the Iteration protocol

For example, for something to be considered an Iterable, it needs to adhere to the stipulated requirement that such a thing must have a Symbol.iterator method that returns an Iterator.

For something to be considered an Iterator, it needs to adhere to the requirement of having at least a next method.

And for the value returned from calling the next method on an iterator to be considered valid, it needs to be of a certain shape; that is the value must have a done property and a value property.

So it is obvious that for things to work out fine when working with the iteration protocal, a lot of requirements and structure needs to be satisfied. This is where TypeScript can help.

TypeScript allows us to code while making sure the checks and guarantees required by the iteration protocal are present and can be confirmed at compile time.

To do this, TypeScript provides a couple of interfaces that capture the structures and protocols of iterables and iterators. These interface can then be implemented at development time ensuring the requirements are adhered to.

But in other to be able to make use of these interfaces and compile time guarantees, we need to be able to configure the Typescript compiler appropriately. This post will show how to go about such configuration and it will contain the following sections: