Specifically, the use of a type alias declaration effected a much larger
Yesterday I shrank a TypeScript declaration from 700KB to 7KB by changing one line of code 🔥
In the thread, Rob points out that the reason this happens is because type alias declarations can be inlined, whereas interfaces are always referenced by name.
Let’s have a look at some code that demonstrates this inlining behaviour.
Here’s a TypeScript playground snippet in which a type alias is used to declare the callback…
Recently, I replaced an ESLint rule that was specific to arrays —
no-array-foreach — with a more general rule —
no-foreach — that also effected failures for the
no-foreach rule supports a
types option — so the that the types for which it is enforced can be configured by the developer — and I planned to leverage that by deprecating and re-implementing
no-array-foreach to use
no-foreach internally. …
RxJS — and Rx in general — offers a bunch of guarantees that make it possible to compose observable chains. Specifically, it’s guaranteed that:
There is more information about this in the Observable Contract.
The guarantees allow for the declarative composition of observable chains: developers can focus on composing behaviours rather than keeping track of state. Without the guarantees, developers would be checking for errored or completed sources and composition would be more difficult.
A quirk that stems from these guarantees is that it’s possible for an error channel to be closed. For example, if an error occurs when an observable is being torn down, it’s not possible for that error to be reported to the observer — the observer will have already received a
error notification or will have already been explicitly unsubscribed. In RxJS, observers in this state are referred to (internally) as stopped. …
I thought I’d write up a short post to explain a TypeScript problem that took up far too much of my time.
The TL;DR is that if you have overload signatures for a function that takes a variable number of (initial) arguments, the ordering of the signatures matters in a way that is not obvious. And the ‘simplest’ signature should be placed first.
The types I was working with were in RxJS, but to keep things general let’s use an example that combines a bunch of arrays in some way, like this:
publishReplay operators can be called in two ways: either with or without a selector function. Let’s look at the differences and at why you should almost always pass a selector.
publish is called without a selector, it returns a particular type of observable: a
ConnectableObservable is a little unusual. It does not connect — i.e. subscribe — to its source when a subscriber subscribes. Instead, a
ConnectableObservable subscribes to its source when its
connect method is called.
This behaviour can be used to control the order in which subscriptions occur and to compose observables before a subscription is made to the source. …
A while ago, I wrote a linting rule to highlight an error that I’d made on a few occasions. Let’s look at the error — and its variations — and then at the rule that prevents it.
const developers = employees
.filter(e => e.role === "developer")
.map(e => e.name)
Which is fine. There’s no error in that code.
However, in situations in which you don’t need to filter or map, you might write something like…
Introducing unintentional dependencies on
rxjs-compat is something that I see developers doing every now and then. Let’s have a look at
rxjs-compat to see what it is, how it works and how depending upon it can be avoided.
If you’re only interested in avoiding the dependency, skip to the TL;DR at the bottom of the article.
In RxJS version 6, breaking changes made the library simpler:
Those changes made the library easier to maintain, document and explain, but they created a burden for developers with large RxJS-version-5 codebases: pretty much all RxJS-related code would need to be modified. …
In RxJS version 6.4.0, a change was made to the
shareReplay operator. Let’s look at why the operator needed to be changed, what was changed and how the change can be used to avoid surprises — and bugs.
If you’re only interested in the change, skip to the TL;DR at the bottom of the article.
shareReplay operator was introduced in version 5.4.0.
shareReplay returns a hot, reference-counted observable, but replays the specified number of
next notifications. …
When pipeable operators were introduced in RxJS version 5.5, writing user-land operators became much simpler.
A pipeable operator is a higher-order function: a function that returns another function. And the function that is returned takes an observable and returns an observable. So, to create an operator, you don’t have to subclass
Subscriber. You just write a function.
However, there are situations in which you need to take some extra care. In particular, you need to be careful whenever your operator stores internal state.
Let’s look at an example: a
debug operator that logs received values and their indices to the console. …
I often see code that looks a little like this:
Which seems fine.
Well, it is fine — as long as the
handleError methods do not depend upon the
this context in their implementations.
When unbound methods are passed to RxJS, they will be invoked with an unexpected context for
this. If the method implementations don’t use
this, they will behave as you would expect.
However, there are a number of reasons why, as a general rule, you might want to avoid passing unbound methods:
thisin its implementation. Maybe you’ll have a test that picks it up; maybe you won’t. …