DEV Community

Cover image for Let's learn typescript: 002 - Everyday types
Carlos Giner
Carlos Giner

Posted on

Let's learn typescript: 002 - Everyday types

Basic type definition

These basic types match the ones that we get using the typeof operator in plain javascript, so no big deal here.

const myNumber: number = 5;
const myString: string = 'hello';
const myBoolean: boolean = true;
Enter fullscreen mode Exit fullscreen mode

Functions

Typescript will always check for the number of parameters to be passed to match. But annotations are optional, since if we aren't in strict mode, it will infer any types for the parameters. This is not always a good thing.

//this will work

function greet(name) {
  console.log("Hello, " + name.toUpperCase() + "!!");
}
Enter fullscreen mode Exit fullscreen mode
//this will work too

function greet(name: string) {
  console.log("Hello, " + name.toUpperCase() + "!!");
}
Enter fullscreen mode Exit fullscreen mode

Also, the return type will be inferred, in this case void. But we could define it as well after the parenthesis:

function greet(name: string):void {
  console.log("Hello, " + name.toUpperCase() + "!!");
}
Enter fullscreen mode Exit fullscreen mode

As a rule of thumb, one must avoid explicitly defining types whenever typescript has inferred them right. But these depend a lot on the project and the team's decision. Some folks prefer a more strict approach, and this is useful not only to avoid errors but also for “self-documentation” of the code.

Object types

To define an object simply define each property annotations inside curly braces.

function printCoordinates (obj: {x:number, y:number}) {
 //...
}
Enter fullscreen mode Exit fullscreen mode

Working with functions is very likely that some of the arguments are undefined or could be optional. So keep in mind this, and put a “?” symbol.

function addToShoppingCart(obj: {code: number; name: string; description?: string }) {
  //do something
}
Enter fullscreen mode Exit fullscreen mode

💡 **Notice that you can put at the end of the property comma ( , ) or semi-colon ( ; ). They are both valid syntax.**

But take into account that typescript does not prevent the behavior that could happen at runtime, so you have to handle the possibility of the parameter coming undefined.

function addToShoppingCart(obj: {code: number; name: string; description?: string }) {
  console.log(obj.description);
}

addToShoppingCart({ code: 123, name: 'stuff' });
//this will print to the console *undefined*
Enter fullscreen mode Exit fullscreen mode

This example may be a harmful console log, but in a real-world scenario maybe this parameter is passed to another function or gets called one of the string methods, and then it would crash the application. For example:

function addToShoppingCart(obj: {
  code: number;
  name: string;
  description?: string;
}) {
    console.log(obj.description.toUpperCase());
}

addToShoppingCart({ code: 123, name: 'stuff' });
//this will throw an Error: *Cannot read properties of undefined (reading 'toUpperCase')*
Enter fullscreen mode Exit fullscreen mode

So long story short, be careful with the optional properties and handle your undefines, that no one is gonna do it for you…

Union types

This is a helpful feature that lets you combine types to form new types. You’ll find this handy when a function parameter could have more than one type.

function findUser(userId: string | number,  name: string) {
    //...
}
Enter fullscreen mode Exit fullscreen mode

Now the logical question will be, if userId could be both types, how would typescript know what methods to suggest? For example

function findUser(userId: string | number,  name: string) {
    userId.toLowerCase(); 
}

//This will give an Error: *Property 'toLowerCase' does not exist on type 'number'.*
Enter fullscreen mode Exit fullscreen mode

Well, unfortunately, there is no fancy solution, we have to handle this with our own hands, coding some conditions and leveraging the typeof operator. This is called by the typescript documentation as narrowing.

function findUser(userId: string | number,  name: string) {
    if (typeof userId === 'string'){
        userId.toLowerCase(); 
    } else {
        //...
  }
}
Enter fullscreen mode Exit fullscreen mode

So that's it for the common, not-so-crazy things that you will see in a typescript code. See you in the next article.

Top comments (0)