me
Published on

Typescript overview

Authors
  • avatar
    Name
    Omer ATAGUN
    Twitter

A story

Well, actually i was not planning write such thing but considering i got messages from a fellow colleagues, i decided to expose my feelings about typescript and why type safety of a software is important or when you should start/stop using it.

Couple of days ago, a colleague of mine complained a little that the current employer of him decided to go with react proptypes. If you have not work with it so far, here is the link

React PropTypes

I was thinking why there could be such decision to make while there is a typescript as known as superset of javascript and the best tool you could ever use if you are to develop anything on javascript.

All of a sudden, i dove into thoughts and considered couple of aspects that could make me choose to go with propTypes.

  • Legacy applications
  • Relatively less experienced team in terms of writing types. This is maybe the most important trade off to consider. If your team is about to spend x3 time onto a feature just because there is a complexity of typescript. This may affect your business very badly.
  • Maybe its just right for the job. Thoughs on budget, team, time etc.

I have hated entire my life thinking on anything radically. In a world of probabilities, nothing could ever be this is good, or this is bad. Even if the wrong choice has been made, as long as there is enough energy and will to do better, you'll do better :)

Allright, now lets actually start talking about typescript as we have promised in the title of this blog post.

So why do we need it ?

We do not need to be software engineer to understand this. A very common way to express ourselves to people when we do something together or order something.

E.g when you ask to your friend whom is on the way to buy a pen that if he/she can buy it for you, what would you say ? i need a pen. Yeah all right, but how many different types of pens are there ? no need exact quantity but if an item has more than 1 types, you need to specify :)

It is with variables the same especially on javascript. Imagine a tree, any would be on top of that and branches would go down to primitive types such as strings, array, object, number. Then those would branch to more detailed types.

We need to specify for our fellow developers to build something meaningful out of it. Lets give a 2 bare example;


const myCrazyFunction = (a,b) => {
  return a+b
}

As a client of this function ( a fellow collague ) i have no clue what i could ever pass, or what to expect. You may say that allright mate, open this function and see that actually sums 2 numbers, or at least intend to do so. This was for simple example, but if there is something does more stuff than simply summing 2 numbers. And if my piece of code is open to human errors, there will always be human errors. My duty is to reduce them as less as possible.


const myCrazyFunction = (a: number, b: number): number => {
    return a+b
}

Now we know that arguments must be a number and this function will return a number. We'd never expect anything else than that. Alright, we are done with this example. Lets make some use case.

interface HumanProps {
  name: string
  zPosition: number
  armSize: number
  legSize: number
  eyeColor: string
  move: () => void
}
export class Human {
  private human: HumanProps

  constructor(human : HumanProps) {
    this.human = human
  }

  getArmSize(): HumanProps['armSize'] {
    return this.human.armSize
  }

  getLegSize(): HumanProps['legSize'] {
    return this.human.legSize
  }

  getEyeColor(): HumanProps['eyeColor'] {
    return this.human.eyeColor
  }

  move(): HumanProps['move'] {
    return this.human.move
  }
}

const John = new Human({
  name: 'John',
  zPosition: 0,
  armSize: 1,
  legSize: 2,
  eyeColor: 'green',
  move: () => {
    console.log('moved')
  },
})

When you instantiate your new human in our case its John, you know exactly what kind of properties a human could have to be created. Its nice right, you exactly know what to expect when and if you use any of these methods.

So far so good, any flame ?

Nothing is perfect my friend. When u dive into especially generics, things are a little bit messy.

E.g

export declare function groupBy<T, K extends T>
(key: (value: T) => value is K)
: OperatorFunction<T, GroupedObservable<true, K>
| GroupedObservable<false, Exclude<T, K>>>;

Do not worry its not you. Do not also get me wrong, its okay to write this and it does its job except reading so symbolic and long type will confuse anyone. This is a mix of generic and union types that expects key and value to group by and returns Observable type.

Lets make some other example that has generic with a condition in it.

interface SomeClassPropsDetails<TIsAlive> {
  isAlive: TIsAlive
  name: string
  surname: string
  address: string
}

interface SomeOtherClassPropDetails<TIsAlive> {
  isAlive: TIsAlive
  name: number
  surname: number
  address: number
}

export type SomeObjectProps<TIsAlive = boolean> = TIsAlive extends true
  ? SomeClassPropsDetails<TIsAlive>
  : SomeOtherClassPropDetails<TIsAlive>

const myObject: SomeObjectProps = {
  isAlive: true,
  name: '0',
  surname: '0',
  address: '0',
}

const yourObject: SomeObjectProps = {
  isAlive: false,
  name: 0,
  surname: 0,
  address: 0,
}

What we have accomplished above is that, we set Type called TIsAlive and defaulted to boolean. We said if TIsAlive is true, then this SomeClassPropsDetails should be referenced, otherwise the other one.

The difference from the first one is that we can easily read this is type of isAlive property rather typing T only. Because once complexity increases, explicit definitions will always help. We could write T,K,Y and all other symbolic representations, we'd be lost in it.

Certainly these are pretty starter/basic examples but since you have idea how things can get wild syntactically, any way of simplifying these would help. If there is a chance to avoid these, should always be taken but otherwise your types will be mainly like this. Most likely as author of this type, at some point you will either forget or do not understand what has been done there.. Since any of types like this will create a lot of problems in terms of reading, people who is working with you will ask you questions in the end. Remember, our goal was to wipe out questions. You have asked to your friend if you can get one pen, your friend asked you which type? you had to state wooden, you open this particular conversation prone to human errors right. All we have ever wanted was to avoid questions to avoid human errors, if we create another while we are solving one, we did nothing :)

On the other hand, even if your colleague does not understand what is happening there, at least on wrong usage, typescript will throw an error. So we are still a winner in terms of avoiding unknown or potential bugs.

Compiler problems

Oh boy, we said typescript is a superset of javascript right ? So it has its own server to run above your javascript application. has its own compilation and all that ABS, traversal node trees and stuff. Along the way you will have some compiler issues with other compilers for example ( babel-jest, ts-babel ). You will find yourself in a very different bugs ( yes there are ) and end up with spending most of your time either trying to understand why that does not work or you just simply find another way and move on. So we are still not that cool if we quit using it.

Conclusion

If you are writing any kind of javascript code today, it is safe to say that use typescript. You decide at what level it will be helpful and allow you to remain safe. You may as well keep typing any and do it properly later on. It is all about situation as we have said many times before :)

Till the next time, stay hydrated.