So we saw some core types in action - we saw type casting in action,
now let's dive into a bit more advanced types - objects and arrays for example.
Now thus far, I only work with strings of numbers and yes actually HTML input element is an object
in the end, just a specific type of object
but let's have a look at objects in general.
Let's say for whatever reason, when we calculate our result here, we don't want to store that in a constant
result like this or not just in that constant
but instead we also want to create a result container and that should be a Javascript object where we
have the res property and that holds
our result. Now of course, it's a bit redundant to have this extra container but for demo purposes, it's fine.
Now clearly we have an object here,
now in this object we have one property - the res property,
now which type is result container now?
Well it is of type object,
if I add object here, this works,
I can explicitly set this to type object and Typescript won't complain.
Now one problem with this approach is that we don't get the best possible auto completion and type
support.
If I access .res here, I get an error and if I access anything else here, I also get an error.
Now for age, that makes sense but res should definitely work, right,
because we have a res property here.
Well the object type is very general,
it just says it's an object but I have no information about it.
So that's not really the type we want to use day-to-day,
instead we want to be specific and you can define an object type in way more detail in Typescript. Instead
of using object here,
you can use curly braces here in the type assignment and this might look strange at first because it
looks like we are creating an object here
but keep in mind we're on the left side of the equals sign here and we're after a colon,
so this in the end just defines a type and this is just us defining an object type because we can now define
all the key-value pairs we have in this object,
for example we can say this object will have a res property and the type of this res property,
so the values stored in the res property will be a number and now we're making it very clear what's
inside result container.
So now I can access .res here and I can do stuff with it that I can do with numbers but I can't
access to .age for example because there clearly is no age property defined in this object type.
Now of course you can do that but it's redundant because if we remove that we see that's the type Typescript
inferred anyways because again, we can rely on Typescript's type inference and if we initialize an object
with a specific value, then of course Typescript infers the object type to fit that values structure.
So here since I initialize result container with an object that has a res property which holds a
number, Typescript correctly infers that the type of result container is an object type with a res property
which holds a value of type number.
So we don't need to set it explicitly,
I will still do it though to have these for reference but you wouldn't do it in reality because Typescript
inference does its job here.
Now let's take it to the next level,
now let's say we want to store all the result containers in an array now.
So here we could have a results array and now for every time we click
the add button, we reach out to results and we push result container into results and then we log let's
say the results array here. If we do that and we quickly compile this code, let's see what this gives
us. If we reload this page and I add two numbers, you see now I got an array with one element which is
an object which has that res property and the result
and if I now add a second calculation, we get two entries here with these two objects.
So this works as intended but we can add anything to results here.
If I also add let's say the number five here,
this will also work.
Now maybe that is what you need in your app but in most cases, it's probably not what you want.
Now the problem is that I initialize results here and I make it clear that it will be an array but I'm
not specifying which kind of array, which kind of data will be in the array and in Javascript, of course
you can have mixed data
and as I said sometimes you need that but also a lot of the times, you don't need that and you want to
have one data type in an array.
Now you can tell Typescript which data type that should be,
so let's assign a type here
and in this case I want to have a collection of objects in this array and the objects should
have this structure here.
So in that case I can add this as a type
but now I would say that results should be an object of that type but it should be an array holding
such objects
and we make that clear in Typescript by adding square brackets here and with that, we're saying okay this
is an array and the data types in the array will be object of that structure
and now you'll see I get an error down there where I try to push five because five is not assignable
to a parameter of type object which has this structure.
So now again, we avoid an unnecessary mistake by being clear about the types of data we store
and just a side note of course, if we had let's say an array names here which we initialize with a value,
then Typescript would automatically infer the array,
here it infers that this is an array full of strings,
so that is something we can always rely on. Now we can also turn this in a const by the way.
So that is something we can rely on and this is just needed here
if we initialize this with no array or with an empty array and we want to be clear about the types of
data we can add.
Now with that let's take our object here to the next level though. In here,
I now want to also have a function, print,
so I want to the method to be precise because a function in an object is called a method.
We can do that by adding print like this
and in there, I just want to console log this res.
Now I get an error here, I get an error that I can't add a print method here because I clearly
defined that my object will only have one property, res, which is a number,
it won't have a print property which hold a function.
So maybe we should extend our function type here or simply get rid of it here and use inference.
Now this works here and surprisingly, this also works,
I can push this to my array even though in the array, I say nothing about this function here.
Well that is how Typescript simply behaves here,
it doesn't really see this as a problem, that we have more properties than as I defined here,
it's just happy that it gets an object which at least has this res property, it doesn't care that we
have more properties. Still we could be more specific up there and make it clear that any objects that
go into that array should have a print method
and for that we now have a new question to answer, how do we define that
there should be a function in print which has certain types for its possible parameters and certain
return types? Well we assign a type to print and we use a so-called function type here.
This looks like an arrow function here,
we have a list of parameters and then an arrow
but again just as with the object here on the left side of the equal sign, this is not a new function
we create, instead we're just defining the type of a function that will eventually be stored in print
and here I want to have a function which returns nothing, so which has a return type of void and which takes
no parameters
and if it would take parameters, we could simply add them here
but the print function doesn't need any.
So with that, I am making it clear that in results, we have an array of objects where every object has
a res property which is of type number and a print property which actually holds a function, which takes
no parameters and which returns nothing
and with that I can for example call results 0.print here like this and it should just work.
So let's try to compile this and it does compile without errors
and if I now reload, you'll see indeed it prints 10 here and that is coming from this line here. So that's
really nice and useful
and this is how we can work with objects, arrays and functions and how we can work with their types.
Now let's see which other types types Typescript has that we should be aware of.