Reputation: 432
Knockout.js 3.5.0 comes with it's own type definitions on npm.
Let's have this variable x
defined as:
const x: ko.Observable<boolean> = ko.computed(() => true);
Now we got compiler error: Type 'Computed' is missing the following properties from type 'Observable': valueHasMutated, valueWillMutate.
I understand what compiler is trying to tell me, but I think that principally this is wrong - because every computed is also an observable. This behaviour worked well on 3.4.x using type definitions from @types/knockout.
There is the Subscribable
type, which I believe is some "parent" type, and it works in declaration:
const x: ko.Subscribable<boolean> = ko.computed(() => true);
This throws no error. However no type checking is performed on value setter:
x(2); // this is wrong but no compiler error
Can anybody shed some light on these new type hierarchy changes and how should we use it?
Upvotes: 2
Views: 1373
Reputation: 1
I use a combination of an Observable and a Computed as work-around.
InEditMode: Observable<boolean> = ko.observable(false);
InEditModeComputed: Computed<void> = ko.computed(() => {
const result = this.ComposeMode() === EComposeMode.Edit && !this.SaveConsultatieInProgress();
this.InEditMode(result);
});
Upvotes: 0
Reputation: 59
In Knockout 3.5.1, I was able to reference the interface PureComputed
defined in the Knockout package:
import * as ko from 'knockout';
import { Computed, PureComputed, Observable } from 'knockout';
class MyClass
originalComments: string;
comments: Observable<string>;
constructor(serverData: any) {
this.originalComments = serverData.comments || '';
this.comments = ko.observable(this.originalComments);
}
hasChanged: PureComputed<boolean> = ko.pureComputed(() => this.comments() !== this.originalComments);
}
Upvotes: 1
Reputation: 1890
I am going through the upgrade to 3.5.0 myself right now. It is a big change since we should be using the type file that comes with the project and that changes all the names of the classes and gets rid of the global ko. I think these are all good things. I have been happy with the transformation of my code (well, except for trying to get knockout-validation to compile).
I ran into the exact issue you are running into. I knew that when I had assigned a computed to an observable typed variable that it was a hack, but I also knew it would work just fine because the interface was close enough. This upgrade forced me to revisit the hack and to deal with it properly. Here is how I do it now in my code:
I know define the variable as one that takes either an observable or a computed:
class SomeClass {
public value: Observable<boolean> | Computed<boolean>;
}
This allows all the other developers who might be reading the code that value might be a computed so they shouldn't just blindly assign a value to it.
Upvotes: 1
Reputation: 5520
Alternatively you can add in your compiler options
"path" {
...
"knockout": [ "node_modules/@types/knockout" ],
...
}
that way you can use old KO typings until better way to upgrade code would be found
Upvotes: 1
Reputation: 35202
You can use KnockoutComputed<T>
like this:
const x: KnockoutComputed<boolean> = ko.computed(() => true);
Upvotes: 0