DEV Community

Cover image for TypeScript: Standard Built-in Types
Vincent Tong
Vincent Tong

Posted on • Edited on

TypeScript: Standard Built-in Types

Welcome to my second lesson on TypeScript where we'll go more in depth with the built in 'types' that TypeScript includes. If you are new to TypeScript, you should read my initial TypeScript introduction and setup blog here: https://dev.to/vkton115/easy-start-guide-typescript-3ip4

similarly to how javascript has built in types such as

  • numbers
  • strings
  • booleans
  • null
  • undefined
  • objects
  • functions

TypeScript introduces some of its own built-in types such as:

  • any
  • unknown
  • never
  • enum
  • tuple

Inference:

In the last lesson, we learned that we can initialize variables as specific types like so:

let count: number = 123;
Enter fullscreen mode Exit fullscreen mode

this creates a variable with the type of a number set to the value of 123. Because we specified that it was a number, it cannot be reassigned to a different datatype, like a boolean or a string for example.

However, due to inference, we can also write the same login in our TypeScript file as:

let count = 123;
Enter fullscreen mode Exit fullscreen mode

This will achieve the same result and the same variable will not be able to be reassigned to a different datatype. While this does look similar to typing regular JavaScript, the TypeScript compiler will be sure to catch any incorrect reassignments of the variable. There may be some niche situations in which you'd want the variable created to have flexible value types. In these cases, you'd want to utilize any.

ANY

The any typing can be implemented one of two ways. By declaring a variable without assigning it to an inferred value:

let age;
age = 10;
age = 'ten'; //this will work because age was not given a specified type when declared.
Enter fullscreen mode Exit fullscreen mode

Another way to set a typing to any would be similar to setting it to any other type, like so:

let age: any = 10;
age = 'ten';
Enter fullscreen mode Exit fullscreen mode

However, using the 'any' typing goes against what the main functionality of TypeScript. It's merely kept as an option to allow users the ability to declare free-type variables for specific situations where specific typing may not be important or 'code-breaking'.

ARRAYS

In JavaScript, individual elements in an array can be of different types:

let types = [123, 'strings', true];
Enter fullscreen mode Exit fullscreen mode

To specify what type of values the individual elements should be with TypeScript, the format would look something like this:

let numbers: number[]= [1, 2, 3] // this will work because every value in the array is already a number

let age: number[] = [4, 10, '20'] // this won't work because '20' is a string
Enter fullscreen mode Exit fullscreen mode

With inference, the acceptable element types will be whatever types are already present in the array when assigned

let numbersAndStrings = [1, 2, 3, '4'] // this infers that both numbers and strings can exist in this aray
numbersAndStrings.push('hello') // this will work
numbersAndStrings.push(false) // this will error because booleans were not inferred
Enter fullscreen mode Exit fullscreen mode

similarly to how to set a primitive value to an 'any' type, TypeScript arrays can accept any values by initializing it as an empty array.

let anyType = [];
anyType.push(1) //this works
anyType.push('string') // this also works
anyType.push(false) // this works too
Enter fullscreen mode Exit fullscreen mode

CODE COMPLETION

Before we move onto more built-in types, let's talk about one of the key benefits to using TypeScript: Code Completion.

Given a TypeScript Array like:

let numbers = [1, 2, 3]; //inference makes it so all elements are presumed to be numbers
Enter fullscreen mode Exit fullscreen mode

Because TypeScript should now know what type of data each element in the array is, it knows what methods we should have access to. So if we were to iterate through this array, we will receive a list of methods that can be applied to each element after using dot notation like so:

CC

Having this feature is convenient and is one of the ways TypeScript helps with productivity.

TUPLES

Tuples are essentially fixed length TypeScript arrays in which you can specify the type of data that each element index should be. The syntax for TypeScript tuples are as follows:

let person: [string, number] = ['Vincent', 27];
Enter fullscreen mode Exit fullscreen mode

This does a couple of things for us:

1. Tuples make it so we cannot assign the variable to an array of different size than the defined array length.

let person: [string, number] = ['Vincent', 27, 'male'] // error: target only allows for 2 elements

let person: [string, number] = ['Vincent'] // error: target requires 2 elements;
Enter fullscreen mode Exit fullscreen mode

note: using push/pop/shift/unshift methods seems to allow us to bypass this and add/remove values in the array. The reasons for this is unknown to me but at the moment it seems to be a lapse in TypeScripts functionality.

2. Using Tuples also allows us to set the datatype of specific elements in an array.

let person: [string, number] = ['Vincent', 'twenty-seven'] //error index 1 cannot be a string
Enter fullscreen mode Exit fullscreen mode

It is usually best practice to keep the size of the tuples to a minimum (2 elements is usually recommended similar to key-value pair) as it may get harder to distinguish what each value may represent.

ENUMS

Enums(short for enumerated) are a data type that includes values which are predefined. In TypeScript it is initialized with the keyword 'enum':

enum Alphabet {a, b, c}
Enter fullscreen mode Exit fullscreen mode

By default, the first item in the brace's value is set to 0, and each value following it's value will be incremented by 1 so:
a = 0
b = 1
c = 2

You can specify the value of specific item(s) but note that any follow items values will increment by one by default unless otherwise specified.

enum Alphabet {a, b = 20, c}
console.log(Alphabet.a)// 0
console.log(Alphabet.b)// 20
console.log(Alphabet.c)// 21

let letter: Alphabet = Alphabet.b;
console.log(letter) //20 
Enter fullscreen mode Exit fullscreen mode

note: adding const to the beginning of the enum declaration will generate a more optimized and cleaner looking code when you run the compiler.

FUNCTIONS

When it comes to functions, annotating your parameters is important to ensure arguments passed in are of the correct typing:

function count(start: number, incrementer: number){
  return start + incrementer;
}
Enter fullscreen mode Exit fullscreen mode

Here we are declaring a function named count. its parameters, start and incrementer are both assigned to number types and therefore if you tried to pass in a non-number argument to the count function, you will receive an error.

If you wish to set optional parameters in TypeScript there are two ways.
1. Using default values

function count(start: number, incrementer = 1){
  return start + incrementer;
}

count(2) //=> returns 3 (2 + 1)
Enter fullscreen mode Exit fullscreen mode

2. Using '?'

function count(start: number, incrementer?: number){
  return start + (incrementer || 1);
}
count(2) //=> returns 3 (2 + 1);
count (2, 2) //=> returns 4 (2 + 2);
Enter fullscreen mode Exit fullscreen mode

Because incrementer could possibly be undefined, we needed to create a condition to handle that case, hence why we set it to 1.

Also note that due to inference, TypeScript knows that the return value will always be a number type. However, in a function in other cases you may want to specify what type of value your return should be, like this example:

function returnNumber():number{
  return 7;
}//this will work

function returnNumber():number{
  return '7';
}//this won't work
Enter fullscreen mode Exit fullscreen mode

related configs:
noUnusedParameters - when set to true, if a parameter is never used within a function, it will show an error.
noImplicitReturns - when set to true, it will error if a function has a code path that does not explicitly return in a function.
noUnusedLocals - when set to true, it will error if there are any unused variables. This includes variables declared within functions.

OBJECTS

When it comes to JavaScript objects, we're accustomed to being able to add properties with dot/bracket notation like so:

let obj = {};
obj.name = 'Vincent';
obj.age = 27;

console.log(obj) => // {name: Vincent, age, 27}
Enter fullscreen mode Exit fullscreen mode

However, in TypeScript, we need to define the body of the object before we can change its properties as we will not be able to add/change properties that do not match the object that we defined.

let contactInfo: {
name: string,
phone: number,
fax?: number
} = {name: 'Vincent', phone: 123_456_7890}
Enter fullscreen mode Exit fullscreen mode

note: numbers in TypeScript can be split with an underscore(_) to segment it

As you can see, we initially defined the structure and typing of each key's value in the body of the object. The fax is set to optional with the '?' so therefore we do not need to include it when we assign the initial value of the object. Using the '?' is generally not recommended as it can cause unforeseen errors when compiling, however in this case it makes sense as not every person may have a fax machine.

And finally since we defined the types of each key's value, they can be reassigned as long as they are being reassigned to the same datatype.

contactInfo.phone = 987_654_3210 // this is an ok reassignment
contactInfo.phone = "(123)-456-7890" //this won't work because it expects a number and not a string.
Enter fullscreen mode Exit fullscreen mode

CONCLUSION

Thank you for taking the time out to read this TypeScript tutorial. I hope I was able to help you understand the standard built-in types that TypeScript provides. Stay tuned for more information on more advanced types.

Top comments (0)