How can I inherit a knockout class using Typescript?

I am using knockout 3.x with Typescript, and I want to create a strongly typed collection class that inherits from KnockoutObservableArray<T>, so that my type can be an observable array, but also have its own methods. So I tried this:

export class Emails implements KnockoutObservableArray<Email>
{
    //add a new email to the list
    addItem() : void
    {
        var email = new ContactEmail();
        ...
        this.push(email);
    };
}

But this gives me the following error:

Class Emails declares interface KnockoutObservableArray<Email> but does not implement it:
Type 'Emails' is missing property 'extend' from type 'KnockoutObservableArray<Email>'.

If I try to add a method extend, then this requires me to implement the method peek, etc., offering me to implement everything KnockoutObservableArray. But I do not want to redefine it, I want to expand it, and since it KnockoutObservableArrayis an interface, not a class, I see no way to do this. Is there any way?

+4
4

, .

?

, .

, JavaScript . " ", , , , ( ) #, , #.

, , Type Script, TS JS-, JS .

JS , , .

JSON #, - , HTML.

, , , .

.

, , . , , .

, :

JS + Bootstrap + Icons + html binding

:

knockoutjs

, DOM, , , , .

, - / JS, .

" , ?"

, .

var DirectoryEntryViewModel = (function ()
{
  function DirectoryEntryViewModel(inputRecord, parent)
  {
    this.Pkid = ko.observable(0);
    this.Name = ko.observable('');
    this.TelephoneNumber = ko.observable('');
    this.myParent = parent;

    ko.mapping.fromJS(inputRecord, {}, this);

  }

  DirectoryEntryViewModel.prototype.SomePublicFunction = function ()
  {
    // This is a function that will be available on every row in the array
    // You can call public functions in the base VM using "myParent.parentFunc(blah)"
    // you can pass this row to that function in the parent using  "myParent.someFunc(this)"
    // and the parent can simply do "this.array.pop(passedItem)" or simillar
  }

  return DirectoryEntryViewModel;
})();

var IndexViewModel = (function ()
{
  function IndexViewModel(targetElement)
  {
    this.loadComplete = ko.observable(false);
    this.phoneDirectory = ko.observableArray([]);
    this.showAlert = ko.computed(function ()
    {
      if (!this.loadComplete())
        return false;
      if (this.phoneDirectory().length < 1)
      {
        return true;
      }
      return false;
    }, this);

    this.showTable = ko.computed(function ()
    {
      if (!this.loadComplete())
        return false;
      if (this.phoneDirectory().length > 0)
      {
        return true;
      }
      return false;
    }, this);

    ko.applyBindings(this, targetElement);
    $.support.cors = true;
  }

  IndexViewModel.prototype.Load = function ()
  {
    var _this = this;
    $.getJSON("/module3/directory", function (data)
    {
      if (data.length > 0)
      {
        _this.phoneDirectory(ko.utils.arrayMap(data, function (item)
        {
          return new DirectoryEntryViewModel(item, _this);
        }));
      } else
      {
        _this.phoneDirectory([]);
      }
      _this.loadComplete(true);
    });
  };

  return IndexViewModel;
})();

window.onload = function ()
{
  var pageView = document.getElementById('directoryList');
  myIndexViewModel = new IndexViewModel(pageView);
  myIndexViewModel.Load();
};

- , ( , ), .

, , JSON, ( RequireJS ), // , .

, , .

, typescript, JS TS, TS, .

, ( github - http://github.com/shawty clone), , , , , , ( ), .

, . , , , KO, , , , , .

, , , JS , .

, Shawty

+2

, , - , extends KnockoutObservableArray , implements .

, Typescript. KnockoutObservableArrayStatic, , ko.observableArray.

. :

export class Emails
{
    collection = ko.observableArray<Email>();

    //add a new email to the list
    addItem() : void
    {
        var email = new ContactEmail();
        ...
        this.collection.push(email);
    };
}

DOM - :

<div data-bind="foreach: myEmails.collection">
...
</div>
+2

implements , , ... , ( KnockoutObservableArray<T>.

, , , , KnockoutObservableArray<T> ( ).

interface KnockoutObservableArray<T> extends KnockoutObservable<T[]>, KnockoutObservableArrayFunctions<T> {
    extend(requestedExtenders: { [key: string]: any; }): KnockoutObservableArray<T>;
}

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 KnockoutObservableArrayFunctions<T> {
    // General Array functions
    indexOf(searchElement: T, fromIndex?: number): number;
    slice(start: number, end?: number): T[];
    splice(start: number): T[];
    splice(start: number, deleteCount: number, ...items: T[]): T[];
    pop(): T;
    push(...items: T[]): void;
    shift(): T;
    unshift(...items: T[]): number;
    reverse(): T[];
    sort(): void;
    sort(compareFunction: (left: T, right: T) => number): void;

    // Ko specific
    replace(oldItem: T, newItem: T): void;

    remove(item: T): T[];
    remove(removeFunction: (item: T) => boolean): T[];
    removeAll(items: T[]): T[];
    removeAll(): T[];

    destroy(item: T): void;
    destroy(destroyFunction: (item: T) => boolean): void;
    destroyAll(items: T[]): void;
    destroyAll(): void;
}

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;
}

interface KnockoutObservableFunctions<T> {
    equalityComparer(a: any, b: any): boolean;
}

... push remove . ( : , - Knockout , , extends, implements ..)

- , , , , , KnockoutObservableArray<Email>. , . , .

/// <reference path="scripts/typings/knockout/knockout.d.ts" />

interface MyObservableArray<T> {
    push(...items: T[]): void;
    remove(item: T): T[];
}

class Email {
    user: string;
    domain: string;
}

class ObservableEmailArray implements MyObservableArray<Email> {
    push(...items: Email[]): void {

    }

    remove(item: Email): Email[] {
        return [];
    }
}

var observableArrayOne: KnockoutObservableArray<Email> = ko.observableArray<Email>();
var observableArrayTwo: MyObservableArray<Email> = new ObservableEmailArray();

function example(input: MyObservableArray<Email>) {
    // Just an example - will accept input of type MyObservableArray<Email>...
}

example(observableArrayOne);

example(observableArrayTwo);
+1

.

   export class ShoppingCartVM {
        private _items: KnockoutObservableArray<ShoppingCartVM.ItemVM>;
        constructor() {
            this._items = ko.observableArray([]);
            var self = this;
            (<any>self._items).Add = function() { self.Add(); }
            return <any>self._items;
        }

        public Add() {
            this._items.push(new ShoppingCartVM.ItemVM({ Product: "Shoes", UnitPrice: 1, Quantity: 2 }));
        }
    }

You cannot throw ShoppingCartVM into a KnockoutObservableArray, but you can enter a common interface, as Steve Fenton replied.

0
source

All Articles