Search code examples
javascripttypescriptknockout.jstypeof

Get field type in Typescript


I have class in Typescript. It has some fields

field1 : ko.observable<number>();
field2 : ko.observable<string>('');
...

In some function in another class I've tried to loop through every object field and for fields of type number I need to perform some modifications.

How can I detect this?


I've tried next, but always get type as string which is logically. locationModel filled with values from HTML form, where inputs is of type text

 Object.keys(locationModel)
 .forEach(property => {
                if (typeof locationModel[property]() === 'number') { }
                else{ }
            }
        });

Solution

  • If you want to put automatic type conversion into knockout you can create an extender for that.

    In its most basic form it could return a writable computed that either:

    • converts the incoming value on write and stores the converted value in the observable, or
    • stores the incoming value in the observable unchanged and converts it on read.

    An implementation of the latter could like this – run the snippet below and note how the type reflects in the viewmodel:

    ko.extenders.type = function (target, type) {
        var typedValue = ko.pureComputed({
            read: function () {
                var value = target();
                if (typeof value === "undefined" || value === null) {
                    return value;
                } else {
                    return type(value);
                }
            },
            write: target
        });
        typedValue.raw = target;
        return typedValue;
    };
    
    var vm = {
        num: ko.observable().extend({type: Number}),
        str: ko.observable().extend({type: String})
    };
    
    ko.applyBindings(vm);
    
    // init some values
    vm.num(100);
    vm.str(100);
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
    
    Num: <input data-bind="value: num"> (raw: <span data-bind="text: num.raw"></span>)<br>
    Str: <input data-bind="value: str"> (raw: <span data-bind="text: str.raw"></span>)<br><br>
    
    <hr>
    View Model:<br>
    <pre data-bind="text: ko.toJSON($root, null, 2)"></pre>