TypeScript Tutorial For Beginners: The Missing Guide - Part 2
Tags: typescript, javascript, beginners
Published: 2019-09-26 07:10:19

---
title: "TypeScript Tutorial For Beginners: The Missing Guide - Part 2"
published: true
description: "What is TypeScript and why you may want to use it? Learn more with this TypeScript tutorial for beginners and start adding types to your JavaScript code!"
tags: typescript, javascript, beginners
canonical_url: https://dev.to/valentinogagliardi/typescript-tutorial-for-beginners-the-missing-guide-part-1-52hj
series: "TypeScript Tutorial For Beginners"
cover_image: https://thepracticaldev.s3.amazonaws.com/i/dvepdqnprwn7kzst9v5a.png
---

**Just crossed 5k follower on dev.to! Thank you everyone! What a fantastic community! Who's on Twitter too? Let's connect => [I'm here](https://twitter.com/gagliardi_vale)**.

_What is TypeScript and why you may want to use it? Learn more with this TypeScript tutorial for beginners and start adding types to your JavaScript code!_

_Originally published on [valentinog.com/blog](https://www.valentinog.com/blog/typescript/)_

## In this episode:

- TypeScript types
- TypeScript interfaces
- typing variables

## Dipping our toes into TypeScript types

TypeScript revolves around **types** and looks like our code has no types at all. Time to add some. We're going to fix function parameters first. By looking at how the function is called it seems it takes strings as arguments:

```js
filterByTerm("input string", "java");
```

Are we sure? Let's add your first **type annotation** to the function. Here's how:

```typescript
function filterByTerm(input: string, searchTerm: string) {
    // omitted
}

// omitted
```

That's it! By adding types to the parameters we're migrating our code from pure JavaScript to TypeScript. But if you try to compile the code:
 
```bash
npm run tsc
```
 
here's what happens:

```text
filterByTerm.ts:5:16 - error TS2339: Property 'filter' does not exist on type 'string'.
```

Can you see how TypeScript is guiding you? The problem is with the filter function:

```typescript
function filterByTerm(input: string, searchTerm: string) {
    // omitted
  return input.filter(function(arrayElement) {
    return arrayElement.url.match(regex);
  });
}
```

We're telling TypeScript that "input" is a string but later in the code we call the [filter method](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) on it, which belongs to arrays. What we really want instead is marking "input" as an array of something, maybe an array of strings?

For doing so you have two options. Option 1 with string[]:

```typescript
function filterByTerm(input: string[], searchTerm: string) {
    // omitted
}
```

or if you like this syntax, option 2 with Array<string>:

```typescript
function filterByTerm(input: Array<string>, searchTerm: string) {
    // omitted

}
```

Personally I like option 2 more. Now let's try to compile again (npm run tsc) and here it is:

```text
filterByTerm.ts:10:14 - error TS2345: Argument of type '"input string"' is not assignable to parameter of type 'string[]'.

filterByTerm("input string", "java");
```

TypeScript doesn't want to leave us alone I suppose. Don't blame it, **we marked input as an array of strings and now we're trying to pass in a string**. That's an easy fix! Let's **pass an array of strings instead**:

```typescript
filterByTerm(["string1", "string2", "string3"], "java");
```

And here's the complete code so far:

```typescript
function filterByTerm(input: Array<string>, searchTerm: string) {
  if (!searchTerm) throw Error("searchTerm cannot be empty");
  if (!input.length) throw Error("input cannot be empty");
  const regex = new RegExp(searchTerm, "i");
  return input.filter(function(arrayElement) {
    return arrayElement.url.match(regex);
  });
}

filterByTerm(["string1", "string2", "string3"], "java");
```

Looks good to me. But if you compile it's not (npm run tsc):

```text
filterByTerm.ts:6:25 - error TS2339: Property 'url' does not exist on type 'string'.
```

Ok TypeScript, fair enough. We're passing in an array of strings but later in the code we try to access a property named "url":

```typescript
return arrayElement.url.match(regex);
```

That means we want an **array of objects**, not an array of strings. Let's fix that into the next section!

## TypeScript tutorial for beginners: TypeScript objects and interfaces

We left with TypeScript complaining (what a surprise) because filterByTerm has been passed an array of strings. "url" property does not exists on type string TypeScript yelled. Let's help TypeScript then by passing an array of objects, where every object has the required url property:

```javascript
filterByTerm(
  [{ url: "string1" }, { url: "string2" }, { url: "string3" }],
  "java"
);
```

and while you're there update the function signature so that it takes an **array of objects**:

```typescript
function filterByTerm(input: Array<object>, searchTerm: string) {
    // omitted
}
```

Now let's compile the code:

```bash
npm run tsc
```

and admire the output:

```text
filterByTerm.ts:6:25 - error TS2339: Property 'url' does not exist on type 'object'.
```

Here we go again! It makes sense, at least in TypeScript: the generic [JavaScript object](https://www.valentinog.com/blog/objects/) does not have any property named "url". And for me this is **where TypeScript really starts to shine**.

So what's really the **difference between JavaScript and TypeScript?** It's not that JavaScript does not have types. **JavaScript has types but they are "loose", dynamic**. In other words you can change a variable's type later in the code, or assign new properties to (almost) any object.

Now, at first it will look like alien syntax, but once you get accustomed to **interfaces** you'll start to use them all over the place. But what's an interface by the way? An **interface in TypeScript is like a contract**. Or put it another way an **interface is like a "model" for your entity**.

By taking a look at our code we can think of a simple "model" named Link for an object whose shape should conform to the following pattern:

- it must have a **url** property of **type string**

In TypeScript you would define that "model" with an interface, like so (put the following code at the top of **filterByTerm.ts**:

```typescript
interface ILink {
  url: string;
}
```

With the interface declaration we say "I want to use that shape in my TypeScript code from now on". That's not valid JavaScript syntax of course and it will be stripped away during compilation.

**TIP**: it is a good idea to prefix interfaces with a capital I, that's a convention in TypeScript

Now we can use our interface ILink, which is actually also a **custom TypeScript type**, by fixing the parameter "input":

```typescript
function filterByTerm(input: Array<ILink>, searchTerm: string) {
    // omitted
}
```

With this fix we say to TypeScript "expect an array of ILink" as the input for that function. Here's the complete code:

```typescript
interface ILink {
  url: string;
}

function filterByTerm(input: Array<ILink>, searchTerm: string) {
  if (!searchTerm) throw Error("searchTerm cannot be empty");
  if (!input.length) throw Error("input cannot be empty");
  const regex = new RegExp(searchTerm, "i");
  return input.filter(function(arrayElement) {
    return arrayElement.url.match(regex);
  });
}

filterByTerm(
  [{ url: "string1" }, { url: "string2" }, { url: "string3" }],
  "java"
);
```

At this point all the errors should go away and you can run:

```bash
npm run tsc
```

The compilation step will produce a file named **filterByTerm.js** with plain JavaScript code in the project folder. You can check out the file and see how TypeScript specific declaration are stripped away. 

Since "alwaysStrict" is set true the TypeScript compiler also emits "use strict" at the top of **filterByTerm.js**.

Great job on your first TypeScript code! In the next section we'll explore interfaces a bit more.

## TypeScript tutorial for beginners: interfaces and fields

TypeScript interfaces are one of the most powerful construct of the language. Interfaces help in shaping "models" across your application so that any developer can pick that shape and **conform to it** when writing code.

So far we defined a simple interface, ILink:

```typescript
interface ILink {
  url: string;
}
```

If you want to add more fields to the interface it's a matter of declaring them inside the block:

```typescript
interface ILink {
  description: string;
  id: number;
  url: string;
}
```

Now any object of type ILink must "implement" the new fields, otherwise you get an error. In fact by compiling the code with:

```bash
npm run tsc
```

TypeScript screams at you:

```text
filterByTerm.ts:17:4 - error TS2739: Type '{ url: string; }' is missing the following properties from type 'ILink': description, id
```

The problem is with the argument of our function:

```typescript
filterByTerm(
  [{ url: "string1" }, { url: "string2" }, { url: "string3" }],
  "java"
);
```

TypeScript is able to deduct by looking at the function declaration that the argument is of type Array of ILink. Thus **any object inside that array must have (implement) all the fields defined in the interface ILink**.

Most of the time that's far from optimal. After all we don't know if every new object of type ILink will ever have all the fields. Worry not, to make the compilation pass we can **declare interface's fields optional with a question mark**:

```typescript
interface ILink {
  description?: string;
  id?: number;
  url: string;
}
```

Now both the editor and the compiler will be fine. Yet TypeScript interfaces can do a lot more, in the next sections we'll see how to extend them. But first a brief note about variables in TypeScript.

## TypeScript tutorial for beginners: typing variables

So far you've seen how to **add types to function's parameters**:

```typescript
function filterByTerm(input: Array<ILink>, searchTerm: string) {
    //
}
```

TypeScript is not limited to that, of course you can also add types to any variable. Let's extract function's arguments one by one, for the sake of illustrating the example. First I'm going to extract every single object:

```typescript
const obj1: ILink = { url: "string1" };
const obj2: ILink = { url: "string2" };
const obj3: ILink = { url: "string3" };
```

Notice how **I can say to TypeScript that obj1, obj2 and obj3 are of type ILink**. In "vanilla" JavaScript you would write:

```js
const obj1 = { url: "string1" };
const obj2 = { url: "string2" };
const obj3 = { url: "string3" };
```

Next up we can define an array of ILink like so:

```typescript
const arrOfLinks: Array<ILink> = [obj1, obj2, obj3];
```

And finally the search term:

```typescript
const term: string = "java";
```

Here's the complete code:

```typescript
interface ILink {
  description?: string;
  id?: number;
  url: string;
}

function filterByTerm(input: Array<ILink>, searchTerm: string) {
  if (!searchTerm) throw Error("searchTerm cannot be empty");
  if (!input.length) throw Error("input cannot be empty");
  const regex = new RegExp(searchTerm, "i");
  return input.filter(function(arrayElement) {
    return arrayElement.url.match(regex);
  });
}

const obj1: ILink = { url: "string1" };
const obj2: ILink = { url: "string2" };
const obj3: ILink = { url: "string3" };

const arrOfLinks: Array<ILink> = [obj1, obj2, obj3];

const term: string = "java";

filterByTerm(arrOfLinks, term);
```

Ok, I feel you. **TypeScript looks more verbose and sometimes redundant compared to JavaScript**. But with time you'll see that **the more you add types, the more your code becomes robust**.

**The more you help TypeScript to understand the intent of your code by adding type annotations, the more you'll be fine later. And your developer experience will skyrocket.**

For example now that arrOfLinks is associate with the correct type (array of ILink), your editor is able to infer that every object in the array has a property named **url**, as defined in the interface ILink:

![TypeScript interface infer](https://thepracticaldev.s3.amazonaws.com/i/bk0911wc10l8sfxhs6f6.png)

Now tell me this isn't fantastic because indeed it is. TypeScript has a lot more types besides string, Array and number. 

There are **booleans, tuples, "any", never, enums**. With time you'll learn them all. If you're curious check out the [documentation for the basic types](https://www.typescriptlang.org/docs/handbook/basic-types.html). 

Now let's move on to **extending interfaces**.


******************************************************************

**Stay tuned for part 3!**