Creating Own Types In Typescript

joaosc17

João Costa

Posted on October 8, 2022

Creating Own Types In Typescript

Enum

An enumeration is a type that represents named constants and is often refered to as an enum. It can be very good if meaning of constant value is'nt apparent, this can make the code easier to understand.

enum Response{
     Ok = 200,
     Error = 400
}

if (status === 200) {
  // do something
}

if (status === Response.Ok) {
  // do something
}

Enter fullscreen mode Exit fullscreen mode

The problem with this approach is reflected exactly in numerical enums that are weakly-typed, although string enum are strongly-typed.

enum Level {
  High,
  Medium,
  Low
}
level = 5; // no error accur


enum Level {
  High = "H",
  Medium = "M",
  Low = "L"
}
level = "VH"; // a type error occur

Enter fullscreen mode Exit fullscreen mode

Object Types

In first typescript has a good inferred types system for objects. When hovering the mouse over object you will see the type inferred to object and if you try to change a property to a value of a different type or try to add a property that there are'nt it will return an error.

const JackScore = {
  name: "Jack",
  score: 70
};

JackScore.score = 75; // no error accur
JackScore.score = 'test'; // a type error occur
JackScore.passed = true; // a type error occur
Enter fullscreen mode Exit fullscreen mode

There is also an explicit way to type objects and it has the same strength.

const JackScore: { name: string; score: number; }  = {
  name: "Jack",
  score: 70
};

JackScore.score = 75; // no error accur
JackScore.score = 'test'; // a type error occur
JackScore.passed = true; // a type error occur
Enter fullscreen mode Exit fullscreen mode

The both ways are strongly-typed, although if you wish reuse an object type could be tiring redefinning it each time and that's why type aliases and interfaces is so important.

Type Aliases and Interfaces

Type aliases and interfaces are ways of reuse your types and make typing process faster.

//without types alias and interfaces
const tomScore: { name: string; score: number } = {
  name: "Tom",
  score: 70,
};
const bobScore: { name: string; score: number } = {
  name: "Bob",
  score: 80,
};
const janeScore: { name: string; score: number } = {
  name: "Jane",
  score: 90,
};
//with types alias and interfaces
type Score = {            interface Score {
name:string,       or     name:string,
score:number              score:number
}                        }

const tomScore: Score = { name: "Tom", score: 70 };
const bobScore: Score = { name: "Bob", score: 80 };
const janeScore: Score = { name: "Jane", score: 90 };

Enter fullscreen mode Exit fullscreen mode

What's difference between interface and type alias

Representing primitive types

Type aliases can represent primitive types, but interfaces can't.

type Name = string;
Enter fullscreen mode Exit fullscreen mode

Representing arrays

Both reprensent arrays, although type alias approach is a lot more concise and clearer.

type Names = string[];

interface Names {
  [index: number]: string;
}
Enter fullscreen mode Exit fullscreen mode

Representing tuples

Type aliases can represent tuples types, interfaces can't

type Point = [number, number];
}
Enter fullscreen mode Exit fullscreen mode

Representing functions

Both can represent functions, but type alias is a lot more concise and clearer.

type Log = (message: string) => void;

interface Log {
  (message: string): void;
}
Enter fullscreen mode Exit fullscreen mode

Creating union types

Only type aliases can represent union types.

type Status = "pending" | "working" | "complete";
Enter fullscreen mode Exit fullscreen mode

Representing objects

both can represent types of an object and even the type alias being the most concise approach the equals operator (=) can result in the statement being confused for a variable assignment to an object literal.
We can say that there is a tie here.

type Person = {
  name: string;
  score: number;
};

interface Person {
  name: string;
  score: number;
}
Enter fullscreen mode Exit fullscreen mode

Composing objects

Type aliases and interfaces can both compose objects together.

type Name = {
  firstName: string;
  lastName: string;
};
type PhoneNumber = {
  landline: string;
  mobile: string;
};
type Contact = Name & PhoneNumber;

interface Name {
  firstName: string;
  lastName: string;
}
interface PhoneNumber {
  landline: string;
  mobile: string;
}
interface Contact extends Name, PhoneNumber {}
Enter fullscreen mode Exit fullscreen mode

Authoring a library

One important feature that interfaces have that type aliases don't is declaration merging:

interface ButtonProps {
  text: string;
  onClick: () => void;
}
interface ButtonProps {
  id: string;
}
Enter fullscreen mode Exit fullscreen mode

This is is useful for adding missing type information on 3rd party libraries. If you are authoring a library and want to allow this capability, then interfaces are the only way to go.

💖 💪 🙅 🚩
joaosc17
João Costa

Posted on October 8, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related