erik lieben

Erik Lieben software developer at Effectory and organizer at the dotnet.amsterdam meetup

Creating a typed version of Aurelia’s computedFrom decorator with Typescript

Published , 2 min read (280 words)

When using the computedFrom decorator in Aurelia, you currently need to specify the fields it depends upon using strings. Which is useful, because in Aurelia you could create a field/ property that is only defined in the view and not in the ViewModel.

Now if you are using TypeScript and are very used to things being typed, you might not like these strings, because they could contain typos.

In version 2.1 of TypeScript, the keyof index type query was introduced which allows us to force a string to equal one of the member names of an object. With this new feature, we can make the computedFrom decorated typed.

We can now just create a new decorator and redirect the call to the existing decorator so that the behavior stays the same, but the values you input need to be a key of the type specified as T.

typedComputedFrom.ts

typescript
import {computedFrom as originalComputedFrom} from 'aurelia-framework';
export function computedFrom<T>(...rest: Array<keyof T>) {
return originalComputedFrom(...rest);
}
typescript
import {computedFrom as originalComputedFrom} from 'aurelia-framework';
export function computedFrom<T>(...rest: Array<keyof T>) {
return originalComputedFrom(...rest);
}

Which can now be used in your application as:

typescript
import {computedFrom} from './typedcomputedfrom';
export class App {
public foo = 'a';
public bar = 'b';
@computedFrom<App>('foo')
public get foobar () {
return `${this.foo} ${this.bar}`;
}
}
typescript
import {computedFrom} from './typedcomputedfrom';
export class App {
public foo = 'a';
public bar = 'b';
@computedFrom<App>('foo')
public get foobar () {
return `${this.foo} ${this.bar}`;
}
}

As you can see in the screenshot below, if you use a different value to depend upon the compiler will mark this as an error.

screenshot of error: Argument of type bla is not assignable to parameter of type foo | bar | foobar