TypeScript playground is Opensource and free resource to learn and practice TypeScript skills. π. This learning resource combines markdown tutorials and actual source files with comments to help you learn and refresh TypeScript.
You get to learn and practice, debug TypeScript right in your code editor.
Clone the repo
git clone [email protected]:shashankkatte/ts-playground.git
-
If you are a beginner start with the tutorial here
-
Want to jump into sample Apps? check them here
-
Learn how to contribute to this repo here
Happy Hacking!::+1:
- TypeScript Playground
- Overview
- Sample Applications
- What is TypeScript?
- How TypeScript helps?
- How do we run our code with type script?
- Getting TypeScript - Environment setup
- Executing TypeScript code
- A quick look at How TypeScript helps with Interfaces and Annotations
- Types in TypeScript
- Type Annotations and Type Inference
- Arrays in TypeScript
- Tuples in TypeScript
- Interfaces in TypeScript
- Classes in TypeScript
- Credits and Acknowledgements
Find all the sample Apps and code snippets implemented with TypeScript here : 01_sample_apps
If you are a beginner / need a refresher on basic conceps on TypeScript Start here
With TypeScript, We are adding some additional syntax to our JavaScript code or the type system. Think of it as flexibility of JavaScript with strict type system as in other languages like C# or Java.
TypeScript = JavaScript + A Type system
TypeScript is like a friend sitting behind you while coding, helping you catch errors while you code. πββοΈ
- π Helps us catch errors during development
- π Uses type annotations to analyse our code
- π Only active during development, the browser or node doesnt understand TypeScript, it is just to make development and debugging life easier.
- π Doesnt provide any performance optimization. It is still our JavaScript that runs in the end.
- Create / write TypeScript code (.ts file extension)
- Run it through TypeScript compiler which spits out JavaScript code
- Run this javascript code from compiler as usual in browser or node. (Again now browser or node has no idea we used TypeScript)
Install TypeScript through npm as global module, using this command in the terminal
npm install -g TypeScript
Also install command line tool ts-node that allows us to compile and execute TypeScript code with one command at our terminal
npm install -g ts-node
check the installation by using the type script compiler command with help tag
tsc --help
If it shows all the documentation of tsc command and its options, then you are all set.
We cannot directly execute TypeScript files, we need to first compile TypeScript to JavaScript and then execute the resulting JavaScript file
tsc <filename.ts>
This command compiles the Ts code to JS code
use the usal means to run the resulting JavaScript file
node <filename.js>
This compilation gets tedious pretty soon, w can save one step by using ts node
ts-node <filename.ts>
This command compiles the TS files to JS files and executes the JS file, all in one command.
refer to source code at
01_sample_apps/01_fetchjson/index.ts
Interfaces in TypeScript help define structure of objects in TypeScript. It helps us to catch type errors early while developing code
Annotations let us assign the data type to function arguments. This is a life saver in situations where we tend to mix up order of arguments while calling functions.
Here is an example of interfaces and type annotations:
interface Todo {
id: number;
title: string;
completed: boolean;
}
const logTodo = (id: number, title: string, completed: boolean) => {
console.log(`
The Todo with ID : ${id}
Has a title of: ${title}
Is it finished? ${completed}
`);
};
Refer to
01_sample_apps/01_fetchjson/index.ts
for a complete working exercise.
Great now that we have a taste of TypeScript lets dig deeper from the basics.
In simple terms, a Type in TypeScript is an easy way to refer to the different properties and functions that a value.
A value is anything that we can assign to a variables like strings, numbers, booleans, arrays, undefined etc.
Here's a example:
If we imagine a variable as a bucket and it has a string inside it say "blue". How would you answer the question - Whats in the bucket?
Either you'd say
-
Its a string
-
OR we can say - It is a value that has all the properties and methods that we assume that a string has.
So instead, as a short cut so humans undertand. We just say... It's a string.
Sometimes these types are pretty obvious like strings, but in real world of programming we come across situations where its not so obvious. In a previous example we saw that we defined Todo as an interface type.
So Type in TypeScript is nothing but a short cut, a label or nomenclature of sorts to help us describe what kind of value it is and what can it do.
Every single value in TypeScript has a Type
-
string - "hi there"
-
number - 0.2 0r -20 or 40000
-
boolean - true false
-
Date - new Date()
-
custom type - employee {id:1, name:"john", title:"developer"}
-
Primitive types - Primitive types are all the basic ones that you might guess eg: number, boolean, void, undefined, string, symbol, null.
-
Object types - These are any types that you and I create or any other non-primitive types that are built into the language. E.g: functions, arrays, classes, objects.
-
π Types are used by the TypeScript Compiler to analyse our code for errors. Remember? like that good friend to help find errors while develping.
-
π Types allow other developers to understand what values are flowing around in the codebase. It makes your code more readable, maintainable and collaboration is easy.
Refer to
02_ts_features/01-types.ts
for some code snippet examples and inline explanations.
π EVERYWHERE, well thats the simple answer. You like it or not you will be surrounded by types. every value has a type associated with it.
In this section we will try to digest two different systems in TypeScript, by looking at the in parallel so that we can grasp it better.
-
Type Annotation - Code we add to tell TypeScript what type of value a variable will refer to
-
Type Inference - When TypeScript tries to figure out what type of value a variable refers to on its own!
So you'll see that both refer to finding type of variable.
But, the interesting thing here is they both are kind of at odds with each other. With the former (Type annotation) we are adding some code to tell TypeScript what type a variable is and with latter(type inference) we let TypeScript do the guess work on what type a variable is.
β The big question is doing it manually ( you and I) vs letting TypeScript do the guessing.
First lets understand annotations in next section
We annotate the type of a variable using :
followed by the type name.
Let's look at annotation for basic and object types. Refer to the code snippets and examples at 02_ts_features/02-variables.ts
But do we need to annotate every variable? Read on to Type Inference to find out...
Everytime we create a variable inside our code:
const color = 'red';
we are essentially doing 2 steps
-
Here the left hand side of
=
is the Variable declaration -
right hand side is the variable initialization.
β If we do our declaration and initialization on the same line, TypeScript will figure out the type for us.
So in this example even though we do not annotate color like color: string
TypeScript gets that color is of type string.
To make this even clear if we do the same in two lines, Type script cant figure out anymore
const color;
color = 'red';
If you hover over color after initialization it would say type as any
. (We will look at any shortly)
π Rule of thumb: if we do the declarationa nd initialization in the same line TypeScript will do the TYpe inference for us.
-
Type Inference : ALWAYS! When ever we can we use type infrerence by default. We will let TypeScript figure out the type for us as much as possible
-
Type Annotations - There are 3 Scenarios where we might have to add annotations to help TypeScript find the type
-
βοΈ Whenever a function returns a
any
type and we need to clarify the value -
βοΈ When we declare a variable on one line but initialize on another
-
βοΈ When we want the variable to have a type that can't be inferred.
-
checkout examples on when to use typeannotations at the bottom section of
02_ts_features/02-variables.ts
any
type means that the TypeScript absolutely has no idea what Type a variable or value is! No clue at all!
So any
type is
-
A type , just like
boolean
orstring
-
Means TypeScript has no idea what this is and cant check for correct property references.
π« Avoid Variables with any
at all costs. Its generally a bad thing b'coz TypeScript cant do its job of helping you!
checkout examples on when to use typeannotations at the bottom section of
02_ts_features/02-variables.ts
We got a glimpse of type annotation and functions when we discussed varaiables in 02_ts_features/02-variables.ts
.
const logNumbers: (i: number) => void = (i) => {
console.log(i);
};
However we looked at the annotation for the function variable, The left side of =
sign. Now lets look at how we add annotations for the function itself the right side of =
sign.
Here's whats going on with functions and TypeScript
-
Type Annotation - Code we add to tell TypeScript what type of arguments a function will receive and what type of values it will return
-
Type Inference - TypeScript will to figure out what type of value a function will return.
π The big difference here is we are no longer annotating a variable declaration, instead we are annotating the function itself.
I know this sends our brain on a spin π΅. so lets jump back into code and undertsnad it better. 02_ts_features/03-functions.ts
Lets look at an example where we have an object that describes today's weather
const todaysWeather = {
date: new Date(),
weather: 'sunny'
};
and we have a function that logs out weather
const logWeather = (forecast: {date:Date, weather: string}): void => {
console.log(forecast.date);
console.log(forecast.weather);
};
logWeather(todaysWeather);
Now if we use the modern Javascript syntax to destructure the forecast object and pull the properties, we will have the type annotations like this where we just replace the variable with the actual destructuring statement.
const logWeather = ({date, weather}: {date:Date, weather: string}): void => {
console.log(date);
console.log(weather);
};
βοΈ Note here that the destructuring and the annotations are still seperate, seperated by the
:
Annotating Objects is similar to destructuring argument list we saw in pervious section.
Lets head back into the code and play with it. 02_ts_features/04-objects.ts
When working with Arrays in TypeScript, we are essentially working with plain JavaScript Arrays. You'll still have access to all the familiar Array behaviour as in JavaScript e.g push into an array, for loop etc. All the good stuff!
Typed Array = Arrays where each element is some consistant type of value
In Typescript we generally have similar kind of values in an array. Like an array of strings, an array of numbers. We do not mix them as we could with plain JavaScript.
We can technically have different types in an array, we will look at it in a bit.
Lets head back into code and explore more 02_ts_features/05-arrays.ts
TypeScript can help us in different ways with typed Arrays
-
π TypeScript can do Type inference when extracting values from an array
-
π It can prevent us from adding incompatible values to the array
-
π We can get help with
map
,foreach
,reduce
functions -
π Flexible arrays can still contain multiple different types.
Time to head back into code and explore more 02_ts_features/05-arrays.ts
We use typed arrays anytime we want to represent a collection of records with some arbitary sord order usually of the same type.
A tuple looks very similar to an Array. But the big difference is that in Tuple we have every element in this array looking thing represent one specific property about some record.
While Array represents / organizes a buch or collection of different records, Tuple on the other hand, contains multiple different properties to describe one thing.
Usually inside tuple you mix and match many different types
Lets look at an example:
How would you represent coca-cola π·? the most famous beverage? we might say it has the following properties
-
color property which is a string 'brown'
-
Carbonated property which is a boolean - true
-
Sugar property in grams will be of type number - 40
When coming from a JavaScript background representing a drink this way makes sense. We have one object to represent one drink.
Now if we had to represent this object with an array how would we do that? it would look something like:
['brown', true, 40]
A different data structure that still looks like a drink. However we have lost quite a bit of information in this representation. With earlier representation we as developers could easily undertand that color is brown, carbonated is true and suger is 40.
We have lost those property labels in the representation as an array. You will have to memorise what is what while developing. We have to remember the order of properties.
So this ['brown', true, 40]
is what exactly a Tuple is. We have what looks like an array, and we put in property values into that array in a very specific order. So the ordering part is very critical.
If we mess with the order, the structure becomes useless.
β οΈ When we work with tuples we have a fix order of elements
Head into code at 02_ts_features/06-tuples.ts
π Sorry to break the news this late. We don't use tuples that often in real life and we will see why in a bit.
π Since tuple is included in the official TypeScript documentation you as a developer should at least have a passing idea about it.
Most notably if you are working with a CSV file you might use it, but for most other scenarios you'll find better alternatives.
So then why dont we use it that often? consider this tuple
const carSpecs:[number,number] = [450, 3456];
Now as a developer can you comprehend what this tuple means? what do the numbers mean?
Lets create the same datastructure with an object
const carSpecs = {
horsepower: 450,
weight:3456
}
Now doesnt this make better sense? the object format forces us to put in a key thus making the code more readable.
β In real life you'll see that when ever we need to model some informative data we reach out to object more than tuple. Its all about making the code more readable and in turn making our lives easier.
This is one of the most imporant concept/ feature to grasp in typescript. Understanding Interfaces really well will help you design excellent applications.
π Interfaces + Classes = Strong code reuse with TypeScript
When we create an interface, we are creating a new type that describes the property names and value types of an object. It is a custom type that we define
Conceptually, think of interfaces as being a contract or a design agreement.
π Imagine you are Car maker that makes cars which run on gas and also electric cars.
Now the motor in the cars are very different for Gas and electric cars.
However when a driver gets in the car, they find the save steering wheel the same gas pedal, the same brakes.
Here, you can imagine that the gas pedal, brake pedal and the steeing wheels implement a standard or a common "Interface" that makes it easier for drivers to drive any of these cars in the same manner.
It doesnt matter how the motor, gas pedal and brake pedal works internally... Gas motor or eectric motor, normal steering or power steering, drum brakes or disc brakes.
For the driver, if you turn the steering car turns, press the gas pedal car moves, hit the brake it stops! doesnt marter which type of car you drive. π¨
Understanding Interfaces is a lot easier with code, so lets jump back into code at 02_ts_features/07-interfaces.ts
General strategy for reusable code in TypeScript (Mostly if not always)
-
π Create functions that accept arguments that are typed with interfaces
-
π Objects/classes can decide to 'implement' a given interface to work with a fuction
π Interfaces are used as gate-keepers. If certain object likes to access some functionality it has to impliment the interface.
βοΈ Imagine this real world scenario: Its a cold winter morning and its also raining outside. β
You have two woolen jackets a red one that keeps you warm but is not water proof. It easily gets wets in the rain.
You also have a Blue woolen jacket that gets wet in the rain too, but it came with an additional Yellow rain overcoat.
So to stay toasty and dry you use the blue woolen jacket with the yellow rain overcoat over it.
Lets break it down:
-
π Both the red and blue woolen jackets are the objects.
-
π Yellow rain jacket is like an interface
-
π In order to provide you the funtionality of rain protection the blue jacket implements the yellow rain overcoat
-
π If the red jacket also had to provide you the funtionality of protection from rain. it has to impliment the interface - Yello rain overcoat. i.e You have to wear the yello rain over coat.
A class is a blueprint of sorts to create objects with fields(variables) and methods(functions) to represent a thing.
Think of Classes as cookie cutter and objects as actual cookie. πͺ Or think of classes as stensils π to draw shapes and objects as actual shapes drawn.βΎ
Lets jump back into code and discover how classes work in TypeScript. 02_ts_features/08-classes.ts
Modifiers are different keywords that we can place in front of different methods and properties/fields in class.They help us control how can when a method or property can be accessed.
The goal of the modifiers is to restrict access to diffent functions and variables.
There are 3 types of modifiers available
-
Public : This method/property can be called anywhere at anytime
-
Private : This method/property can only be called by other methods in this class.
-
Protected : This method/property can be called by other methods in this class or by other methods in child classes.
By default every method and property that we create in a class will have public modifier attached to it automatically internally.
The most important concept to grap with TypeScript is the interpay of Interfaces and Classes, the design patterns that pake it so powerful. Have a look at the sample app 01_sample_apps/02_maps
to understand how they all play together
All the content and code samples have been collated from multiple, publicly available resources on TypeScript and from Open source collaborators.
Special thanks and mention to some great online instructors : Brad Travesy | maximilian schwarzmΓΌller | Stephen Grider and many many more...