TypeScript basic types
With the growing usage of TypeScript, I think it's time to start learning it. What is it? Why use it? We'll try to answer these questions and learn some basic types.
Last updated: March 5, 2023Recently I've started learning TypeScript (technically, I used to code in Angular, so TypeScript is not new to me, but I wasn't using it since then). I was hesitant at first, not gonna lie. The TypeScript code seemed to me bloated and inelegant. But let's be honest - the only real downside of TypeScript is that you need to spend the time to learn it. I'm only human, after all - the change can be frightening. But change is the only constant in life. It can be good. And with the growing usage of TypeScript, that's a good moment to start learning it. Learn with me!
What is TypeScript?
Fundamentally, TypeScript is a superset of JavaScript. What does this mean? Let me explain. You probably remember sets from school - you know, these intersecting circles. It's a Venn diagram - a graphical representation that shows the logical relation between these sets. There is a similar relationship between JavaScript and TypeScript - TypeScript is a superset of JavaScript, or JavaScript is a subset of TypeScript. Every line of JS code is a valid TS code, but not the other way around.
It means that TypeScript builds up on JavaScript. It adds new features and advantages to the vanilla language. Actually, TypeScript is both a language and a tool. It's also a powerful compiler which you run to compile your TypeScript code to JavaScript. Why? Because browsers only understand JS code.
Why use TypeScript?
Programming is not about typing, it's about thinking.
"Ok, so why bother writing code browsers can't understand?" There are some advantages.
- Above all - TypeScript forces you to think more about your code and goals. All of your intentions are written down - there is no place for guesses.
- TypeScript adds new features - not available in the base language - like interfaces or generics.
- It offers meta-programming features like decorators.
- Because of the compilation step, you can use modern JavaScript syntax without worrying about browser support. It has similar advantages to using Babel.
- Rich configuration options - you can configure the compiler to your needs.
- And as the name suggests, it offers many types. We'll focus on the basic types in the following sections.
- You have better autocompletion in IDEs or code editors.
TypeScript vs. JavaScript Types
JavaScript is a dynamically typed language. Types are resolved during the runtime. It can be beneficial, but it also causes many runtime errors.
TypeScript is statically typed. We define types during development. They don't change during the runtime.
TypeScript Types
Let's start by saying that TypeScript provides additional types to JavaScript. So, there are types available both in JavaScript and TypeScript. And there are types provided by our superset.
The core types available both in JS and TS are:
number
string
boolean
object
array
There are some additional types available in TypeScript like:
Tuple
Enum
Any
Union
Literal
Custom
Type Assignment
JavaScript doesn't understand TypeScript assignments. Types are used by the TS compiler. TypeScript has a built-in feature called type inference. TS does its best to understand the type of a particular variable or constant. So, you don't need to assign it explicitly every time. You can use a colon syntax to assign a type to a variable.
TYPESCRIPT
1let name: string // The name variable has a type of string.
The core primitive types in TypeScript are all in lowercase.
Number
Similarly to the vanilla language, TypeScript does not define different types of numbers. JavaScript numbers are always stored as double-precision floating point numbers, following the IEEE 754 standard, or as big integers.
TYPESCRIPT
1const PI = 3.14 // TypeScript infers it should always be number 3.14.2let age = 25 // TypeScript infers it should be a number type.3// In terms of DiCaprio's girlfriend's maximum age, it's also a constant, I know.4let age: number = 25 // The code works but is redundant, so it's a bad practice.5let age: number // Here it makes sense because there is no variable initialization.
String
To define a string, use double or single quotes. Template strings using backticks are also an option.
TYPESCRIPT
1const maxim = "Medals don't help me sleep at night." // TypeScript infers the string is a constant.2let name = 'Sam' // TypeScript infers it should be a string type.3let name: string // The variable will hold a string.
Boolean
The most basic data type - represents the true or false value. In contrast to JavaScript, there are no "truthy" and "falsy" values in TypeScript.
TYPESCRIPT
1let isDone: boolean
Object
You define object types similarly to standard JS objects. But, instead of key-value pairs, you write key-type pairs. Look closely at syntax - it's slightly different.
TYPESCRIPT
1const person = {2 name: 'Sam',3 age: 664}56// TypeScript infers.7const person: {8 name: string9 age: number10}1112// You can define generic objects like this.13const person: object = {14 name: 'Sam',15 age: 6616}1718// You can also define a more specific object structure.19const person: { name: string } = {20 name: 'Sam',21 age: 66 // This property is not in the type, so it causes an error.22}
Array
In JavaScript, you can mix different data types - one array can consist of strings and numbers. Every JS array is valid in TypeScript. However, TS arrays can be flexible or strict.
TYPESCRIPT
1const person = {2 hobbies: ['Krav maga', 'sneaking']3}45// TypeScript infers.6const person: {7 hobbies: string[]8}910// You can explicitly define a strict array of strings.11let hobbies: string[]1213// You can also define a flexible array.14let hobbies: any[]
Tuple
Tuples are not available in vanilla JavaScript - they are added by TypeScript. Tuple is a fixed length and type array. It can be handy if you know the exact array structure beforehand.
TYPESCRIPT
1const person = {2 role: [3, 'agent']3}45// TypeScript infers.6const person: {7 role: (string | number)[]8}910// You can explicitly define a touple structure.11const person: {12 role: [number, string]13} = {14 role: [3, 'agent']15}
Enum
An enum type is a custom type in TypeScript. It gives you an enumerated list. An enum maps human-readable labels to numbers starting from 0. It is not available in JavaScript, and it compiles down to IIFE.
TYPESCRIPT
1// Labels are often in uppercase.2enum Role {3 AGENT,4 INTEL5}67const person = {8 role: Role.AGENT9}1011// You can change the default behavior of an enum.12enum Role {13 AGENT = 'AGENT',14 INTEL15}
Union
Sometimes you want to accept more than one kind of value. That's where unions come in handy. You can use a pipe character between different types to define a union.
TYPESCRIPT
1// Both parameters in this function can be a string or a number.2function combine(i1: number | string, i2: number | string) {3 const result = i1 + i24 return result5}
Literal
I mentioned this in snippets, but it's time to list it distinctly. A literal type not only says what kind of value a variable should hold, but it says: "this variable should hold this exact value.”
TYPESCRIPT
1const PI = 3.14 // TypeScript expects this specific number, not any number.23function combine(4 i1: number | string,5 i2: number | string6 // A union type combined with literal type - only two possible strings.7 conversion: "as-text" | "as-number"8) {9 const result = i1 + i210 return result11}
Custom
Besides built-in types, TypeScript also allows you to create custom types (also known as type aliases). There is a keyword - type
- for this purpose. You can put anything inside a custom type - string, object structure, or union. After defining your custom type, you can use the alias in multiple places in your code. This way, you can avoid code duplication.
TYPESCRIPT
1// The convention is to define custom types in uppercase.2type State = 'idle' | 'loading' | 'success'34type Person = {5 name: string6 age: number7}
You can use any name for your custom type, but you can't use reserved JavaScript (or TypeScript) keywords like Date
or Math
.
Function Parameter Types
In previous snippets, I set types of function parameters. You can add them after each parameter using standard syntax.
TYPESCRIPT
1// The function takes two parameters, where each parameter is a number.2function add(n1: number, n2: number) {3 return n1 + n24}
Function Return Types
Similarly, you can also set types of function return values. void
is commonly used with functions that don't return any value. It's like the opposite of any
- the absence of having any type at all.
TYPESCRIPT
1function add(n1: number, n2: number) {2 return n1 + n23}45// TypeScript infers.6function add(n1: number, n2: number): number {7 return n1 + n28}910// You can explicitly set the return type,11// but in most cases, let TypeScript infer the type.12function add(n1: number, n2: number): string {13 return n1.toString() + n2.toString()14}1516// You can use the void return type17// if a function doesn't return a value.18function printResult(num): void {19 console.log('Result: ' + num)20}2122// Undefined is a valid type in TypeScript,23// but not if a function doesn't return anything.24function printResult(num: number): undefined {25 console.log('Result: ' + num)26}
Function Type Expressions
There is also the Function
type in TypeScript. It describes properties like bind
and apply
- present in all functions in JavaScript. However, declaring a non-specific function is not very useful. A better way is to describe it using a function-type expression. If it reminds you of arrow functions - you're right - the syntax is similar.
TYPESCRIPT
1// Declaring a non-specific function.2let combineValues: Function34// The function takes two parameters, where each parameter is a number.5// The function overall returns a number.6let combineValues: (a: number, b: number) => number
Unknown
There is another type unknown
to us (hehe). It is similar to any
, but it's safer. You can't do anything with the unknown
type.
TYPESCRIPT
1let input: unknown2let name: string34input = 55name = 'Sam'6// This won't work because the unknown7// is not guaranteed to be a string.8name = input
TYPESCRIPT
1let input: any2let name: string34input = 55input = 'Sam'6// On the other hand, this will work7// because any is the most flexible type.8name = input
Never
Some functions in JavaScript never return a value. "Wait, wait, how that's different from the void?" We need to dive a little deeper into JavaScript to answer this question.
A function that doesn't explicitly return a value implicitly returns undefined
in JavaScript. You might have noticed that behavior with functions that log something to the console. Although we ignore the return value, it is there. That's a good use case for the void
in TypeScript.
A function that has the never
type never returns. It even doesn't return undefined
implicitly. Such a situation occurs when a JavaScript function throws an error.
TYPESCRIPT
1// This function never produces a value. It crashes the script.2function generateError(message: string, code: number): never {3 throw { message: message, errorCode: code }4}
Ok. . .I never (hehe) said I'll cover all types in one blog post. I'll end here. TypeScript offers even more primitive and advanced types helping you produce more predictable and maintainable code. I'll cover more advanced concepts like generics, interfaces, or decorators in the future. In the meantime, you can check the following links.