Question

Is there any sample of using TypeScript with KnockoutJS? I'm just curious as to how they would work together?

Edit

Here is what I have, seems to work

declare var ko: any;
declare var $: any;
class ViewModel {
    x = ko.observable(10);
    y = ko.observable(10);

}

$(() => {
    ko.applyBindings(new ViewModel());
});

This generates into the following Javascript:

var ViewModel = (function () {
    function ViewModel() {
        this.x = ko.observable(10);
        this.y = ko.observable(10);
    }
    return ViewModel;
})();
$(function () {
    ko.applyBindings(new ViewModel());
});
Was it helpful?

Solution

Look at DefinitelyTyped.

"TypeScript type definitions repository for popular JavaScript libraries"

OTHER TIPS

I made this little interface to get static types for Knockout:

interface ObservableNumber {
        (newValue: number): void;               
        (): number;                             
        subscribe: (callback: (newValue: number) => void) => void;
}
interface ObservableString {
        (newValue: string): void;               
        (): string;                             
        subscribe: (callback: (newValue: string) => void) => void;
}
interface ObservableBool {
    (newValue: bool): void;             
    (): bool;                               
    subscribe: (callback: (newValue: bool) => void) => void;
}

interface ObservableAny {
    (newValue: any): void;              
    (): any;                                
    subscribe: (callback: (newValue: any) => void) => void;
}

interface ObservableStringArray {
    (newValue: string[]): void;
    (): string[];
    remove: (value: String) => void;
    removeAll: () => void;
    push: (value: string) => void;
    indexOf: (value: string) => number;
}

interface ObservableAnyArray {
    (newValue: any[]): void;
    (): any[];
    remove: (value: any) => void;
    removeAll: () => void;
    push: (value: any) => void;
}

interface Computed {
    (): any;
}

interface Knockout {
    observable: {
        (value: number): ObservableNumber;
        (value: string): ObservableString;
        (value: bool): ObservableBool;
        (value: any): ObservableAny;
    };
    observableArray: {
        (value: string[]): ObservableStringArray;
        (value: any[]): ObservableAnyArray;
    };
    computed: {
        (func: () => any): Computed;
    };
}

Put it in "Knockout.d.ts" and then reference it from your own files. As you can see, it would benefit greatly from generics (which are coming according to the specs).

I only made a few interfaces for ko.observable(), but ko.computed() and ko.observableArray() can be easily added in the same pattern. Update: I fixed the signatures for subscribe() and added examples of computed() and observableArray().

To use from your own file, add this at the top:

/// <reference path="./Knockout.d.ts" />
declare var ko: Knockout;

Try my realisation of TypeScript interface declarations (with simple example)
https://github.com/sv01a/TypeScript-Knockoutjs

Nothing would change in terms of the way knockout bindings are declared in the markup however we would get the intellisense goodness once the interfaces are written for the knockout library. In this respect it would work just like the jquery Sample, which has a typescript file containing interfaces for most of the jQuery api.

I think if you get rid of the two variable declarations for ko and $ your code will work. These are hiding the actual ko and $ variables that were created when the knockout and jquery scripts loaded.

I had to do this to port the visual studio template project to knockout:

app.ts:

class GreeterViewModel {
    timerToken: number;
    utcTime: any;

    constructor (ko: any) { 
        this.utcTime = ko.observable(new Date().toUTCString());
        this.start();
    }

    start() {
        this.timerToken = setInterval(() => this.utcTime(new Date().toUTCString()), 500);
    }
}

window.onload = () => {
    // get a ref to the ko global
    var w: any;
    w = window;
    var myKO: any;
    myKO = w.ko;

    var el = document.getElementById('content');
    myKO.applyBindings(new GreeterViewModel(myKO), el);
};

default.htm:

<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title>TypeScript HTML App</title>
    <link rel="stylesheet" href="app.css" type="text/css" />
    <script src="Scripts/knockout-2.1.0.debug.js" type="text/javascript"></script>
    <script src="app.js"></script>
</head>
<body>
    <h1>TypeScript HTML App</h1>

    <div id="content" data-bind="text: utcTime" />
</body>
</html>

I am using https://www.nuget.org/packages/knockout.editables.TypeScript.DefinitelyTyped/ and it has all interfaces for Knockout.

Ok so just use the following command to import the knockout types or tds.

npm install @types/knockout

This will create a @types directory in your projects node_modules directory and the index knockout type definition file will be in a directory named knockout. Next, through a triple-slash reference to the types file. This will give great IDE and TypeScript features.

/// <reference path="../node_modules/@types/knockout/index.d.ts" />

Finally, just use a declare statement to bring the ko variable into scope. This is strongly-typed so hello intellisense.

declare var ko: KnockoutStatic;

So now you can use KO just like in your javascript files.

enter image description here

Hope this helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top