Search code examples
javascriptknockout.jstypescriptdurandaldefinitelytyped

property 'isvalid' does not exist on type 'KnockoutObservable'


I have just started switching from javascript to typescipt. I am using knockout for obvious advantages it has to offer.

I need to define a knockout computed observable which is dependent on the value of another knockout observable. Return true if the observable is valid else return false.

This is how I have structured the code -

class anyClass { 

    private address: KnockoutObservable<any> = ko.observable().extend({ required : true});

    private canPrintAddresses : KnockoutComputed<boolean> = ko.computed((): any => {

        if (this.address.isValid()) {    
            return true;
        }
        else
            return false;
    });
}

I even tried to define the computed inside the constructor, but the compiler is indifferent. I don't know where I am going wrong, but the compiler keeps on giving error - "property 'isValid' does not exist on type 'KnockoutObservable'".

Since, I am also using durandal, so I tried to define it inside the activate event handler, but then this requires the evaluation to be done on the activation of the page when there is no value attached to the observable.

Please help.


Solution

  • The compiler is correct. In knockout, property 'isValid' indeed does not exist on KnockoutObservable.

    Let's have a look at the knockout.d.ts file which ships with knockout:

    interface KnockoutObservable<T> extends KnockoutSubscribable<T>, KnockoutObservableFunctions<T> {
        (): T;
        (value: T): void;
    
        peek(): T;
        valueHasMutated?: { (): void; };
        valueWillMutate?: { (): void; };
        extend(requestedExtenders: { [key: string]: any; }): KnockoutObservable<T>;
    }
    
    interface KnockoutSubscribable<T> extends KnockoutSubscribableFunctions<T> {
        subscribe(callback: (newValue: T) => void, target?: any, event?: string): KnockoutSubscription;
        subscribe<TEvent>(callback: (newValue: TEvent) => void, target: any, event: string): KnockoutSubscription;
        extend(requestedExtenders: { [key: string]: any; }): KnockoutSubscribable<T>;
        getSubscriptionsCount(): number;
    }
    interface KnockoutSubscribableFunctions<T> {
        notifySubscribers(valueToWrite?: T, event?: string): void;
    }
    

    Notice, there is no "isValid".

    So the question is: What makes you think isValid should be a valid member on an observable? If I had to guess, I'd guess you're using the knockout-validation library which adds extra features for form validation to knockout. If I'm guessing correctly, then I'd also guess that you did not bring in the type definitions files for that library. That library extends the KnockoutSubscribableFunctions<T> interface to include more functionality, including isValid().

    interface KnockoutSubscribableFunctions<T> {
        isValid: KnockoutComputed<boolean>;
        isValidating: KnockoutObservable<boolean>;
        rules: KnockoutObservableArray<KnockoutValidationRule>;
        isModified: KnockoutObservable<boolean>;
        error: KnockoutComputed<string>;
        setError(error: string): void;
        clearError(): void;
    }
    

    Once you include those type definitions, you should be good to go. They are available at the definitely typed repository:

    https://github.com/borisyankov/DefinitelyTyped/blob/master/knockout.validation/knockout.validation.d.ts