Partial utility type in Typescript

Typescript is excellent for type safety as it prevents us from making mistakes when declaring new objects. That said, an object is sometimes created by aggregating data from different sources (different API calls, for instance).

For instance, say we have the following interfaces:

We have to create an instance of the Question object, but let’s imagine that creating that object requires several steps. In the first step, I retrieve data for the question itself, and in the second step, I have to retrieve the list of options.

At first, my Question object would look like this:

But this code won’t compile, as myQuestion is missing the options property. We could assign an empty array to options, or we could make it optional in the interface using this syntax: options?: Option[];

All of that seems like cheating, though. Instead, we can use the Partial utility type to indicate that our object is in a temporary state:

The compiler is happy with the above code; we don’t have to change our interfaces.

myQuestion is now an object that implements a subset of the Question interface, with all properties marked as optional.

Typescript has several more utility types like Partial. I’ll cover more of those in the upcoming newsletters.

RxJs startWith operator

startWith is an operator that does something straightforward: It takes an existing Observable and makes it emit a default value immediately.

Its marble diagram looks like this:

What are some everyday use cases for startWith? Here is an example where I want to display a loader while data is being loaded from a service:

The loading property is used to decide when to show/hide a loader. This observable would first emit { data: null, loading: true } then the actual data with loading: false.

You can see the complete example here on Stackblitz ( I had fun with Typescript, the async pipe, and generics in that example, too).

A more complex example in this tutorial is Dynamic filtering with RxJs and Angular forms. I describe how to create a text input used to filter a list of states as follows:

We need startWith in that scenario to start the filtering feature before the user has typed anything in the text input. That’s one of the most common use cases for the startWith operator.

Named router outlets

Using the Angular Router is one of the best ways to emulate multiple pages/screens in an Angular application. However, we might sometimes want even more flexibility by having the equivalent of “sub-pages” where sibling elements on a web page can display dynamic content based on the current URL.

Something like this where three different divs can display different components without a parent/child relationship:

Angular allows us to have named router outlets to support such scenarios. We can define several sibling outlets by giving them distinctive names like so:

Then, in our router config, we can define which component goes in which outlet for which path:

Finally, when routing a component to an outlet, we have to repeat some of that config in the form of a rather lengthy command:

The above code will load two different components in two different named outlets. You can see a live example on Stackblitz here.

Using a resolver function or a title strategy to change the page title

Before we get into today’s topic: The Angular Team’s Request for Comments (RFC) for Angular Signals is now open to the public. Feel free to take a look and give your feedback.

Yesterday, we saw how to change an application’s title using the router config. Today, let’s cover more complex scenarios when we need a dynamic title set depending on other factors.

Using a resolver function

First, we might need some processing using a function to extract information from a service or API. In that case, we can use a resolver function that gets that data and returns it:

Note that the signature of that function allows us to return a string, an Observable, or a Promise. That way, we can make an API request to fetch some extra data if needed. For instance, in the above example, getUsername() returns an Observable (code here). This is another excellent example of using the inject function we covered earlier in this newsletter.

Using a title strategy service

For more complex scenarios, Angular allows us to create a custom TitleStrategy. Such strategy takes the form of a service that has to implement an updateTitle method:

Here is an example where I add a prefix to the title, then use the default title from the title property in the router config. Note that we could easily inject other services and perform async operations before setting the new title if needed:

Such title strategy service has to be provided as the default title strategy in our dependency injection configuration as follows:

You can see that example in action here on Stackblitz.

Changing the page title using Angular Router

This is a quick post to showcase a recent addition to the framework that is useful and very simple to implement. We can now have a title property in every route config:

The provided title is set as the page title (in your browser tab) when the user navigates from one page to the next. Just like that:

You can see a code example here on Stackblitz with a live version here. I used standalone components with the new provideRouter function just for the fun of it:

Note that there is also a Title service that can be used if you need to change that title dynamically later. Here’s a short tutorial of mine on that topic: How to change the page title and meta tags with Angular?

Subject, BehaviorSubject, and ReplaySubject

We introduced RxJs Subjects a few weeks back.

BehaviorSubject

The most common type of Subject used with Angular is BehaviorSubject. Why is that? Because a BehaviorSubject has two exciting features that a plain Subject does not have:

  • It starts with a default value, which means it is never empty.
  • When we subscribe to a behavior subject, it will immediately give us the last emitted value.

Imagine subscribing to a magazine and receiving its latest published issue immediately. That’s what a BehaviorSubject does. This is helpful if you have components that need to know about the app’s current user. When the component subscribes to the “current user,” we want to get that info immediately and not wait for the next user update.

Also, since behavior subjects always have a value, they have a getValue() method that synchronously returns the current value.

ReplaySubject

A ReplaySubject is very similar to a BehaviorSubject, with two key differences:

  • No default value
  • Can replay more than just the last value

The constructor parameter determines how many values should be replayed to new subscribers:

Subject

A plain Subject has none of the above capabilities. When a value is emitted, current subscribers receive it, but future subscribers won’t. There is no replaying of the latest value(s), which makes plain Subjects less interesting to work with.

ngOnInit vs. constructor in Angular

Today’s post is all about clarifying when to use a constructor and when to use ngOnInit to initialize data in our Angular components.

From a chronological standpoint, the constructor is called first. Then, once all component inputs are initialized, Angular is going to call ngOnInit.

From that definition, it makes sense to use ngOnInit only when your initialization code needs a @Input value to be set. Something along those lines:

And that’s the only rule. Some might be surprised to read this, but you could initialize everything in your constructor if your component has no inputs. There is no performance impact in doing one or the other.

I would argue that triggering an HTTP request in the constructor is better as it’s going to happen sooner (we’re talking milliseconds, though) than if we do it in ngOnInit.

As a result, in the absence of any official recommendation in the Angular style guide, you can choose one or the other.

Resolver function for the Angular Router

The last router function of our guard series is resolve. It is the replacement for class-based resolvers. A resolver function runs after all guards have run and before the destination component is rendered. Such a function is typically used to preload component data before rendering it on the screen.

For instance, in this example:

heroResolver is a function that returns either some data or a Promise or an Observable of that data. Such data will be stored in the hero property of a data object returned by an Observable from the ActivatedRoute service as follows:

Of course, we could resolve multiple different pieces of data using the following syntax:

resolve: {user: userResolver, session: sessionResolver},Code language: JavaScript (javascript)

A resolver function can use the inject function to use services and resolve data as follows:

export const userResolver: ResolveFn<User> = () => { 
    return inject(UserService).getCurrentUser(); 
 };Code language: TypeScript (typescript)

RxJs share and shareReplay operators

Last week, we covered the difference between hot and cold Observables in RxJs.

Today, let’s talk about how we can make a cold Observable hot. Why would we want that? Say our Observable is an HTTP request we want to trigger before any component subscribes to it. We saw that Observables from the HttpClient are cold, meaning that they only start fetching data when a subscriber comes over.

By making the Observable hot, the HTTP request would get triggered immediately. The share operator would do exactly that for us:

Under the hood, share turns our Observable into a Subject, which can handle multiple subscribers and is hot by default.

The only problem with the above example is that the data could be emitted before any subscriber gets the chance to subscribe to that new hot Observable.

As a result, it makes more sense to use shareReplay instead as it’s going to replay the latest value(s) to any new subscriber (just like a ReplaySubject):

This code is much better because:

  • The request is going to fire instantly before any subscription happens
  • Any future subscriber will receive the same data from that original request instead of firing a new request.

You can look at this blog post for an illustration of the above operators with a code example.

canMatch Router Guard

After introducing guards and the most common guard functions (canActivate, canActivateChild, and canDeactivate), we will cover one slightly different guard that can run when trying to access a route.

canMatch was introduced in Angular 15.1. When canMatch returns false, Angular will continue looking at other routes that would match that path instead of preventing any navigation.

Let’s consider the following example:

With the above code, both routes are configured for the /user path, but if the user is an admin user, they’ll land on an AdminDetails component, and if they’re a regular user, they’ll land on a UserDetails component.

This approach can be helpful when working with multiple user roles that display different components.