Alex Zhukovskiy
Alex Zhukovskiy

Reputation: 10015

How to extend JQuery functions in TypeScript

I'm rewriting some JS code on TypeScript and encounter with problems with module import. For example, I want to write my toggleVisiblity function. Here is code:

/// <reference path="../../typings/jquery/jquery.d.ts" />

import * as $ from "jquery";

interface JQuery {
    toggleVisibility(): JQuery;
}

$.fn.extend({
    toggleVisibility: function () {
        return this.each(function () {
            const $this = $(this);
            const visibility = $this.css('visibility') === 'hidden' ? 'visible' : 'hidden';
            $this.css('visibility', visibility);
        });
    }
});

const jQuery = $('foo');
const value = jQuery.val();
jQuery.toggleVisibility();

But the problem is that for unknown reason toggleVisibility is not added to JQuery interface thus I get an error Property 'toggleVisibility' does not exist on type 'JQuery'., although it sees other methods (val, each and so on).

Why is it not working?

enter image description here

Upvotes: 23

Views: 18071

Answers (3)

Alexander Belov
Alexander Belov

Reputation: 11

I had a similar problem but with my bootstrapDP function extending JQuery in the same way.

Solution:

    declare global {
        interface JQuery {
            bootstrapDP: any;  // replace 'any' with the actual type if known
        }
    }

Explanation:

This code declares a global augmentation of the JQuery interface, adding my bootstrapDP method to it. After adding this code, TypeScript should recognize bootstrapDP as a method on jQuery objects.

Here is some documentation about global auhmentation: link

Upvotes: 0

mode777
mode777

Reputation: 3187

Try putting the

interface JQuery {
    toggleVisibility(): JQuery;
}

Inside a seperate file without import/export statements. This works for me. Though it wold be interesting to know why.

EDIT: There is an excellent explanation for this behaviour in this answer to post: How to extend the 'Window' typescript interface

Upvotes: 39

Displee
Displee

Reputation: 720

I got the solution, this worked for me:

Use the JQueryStatic interface for static jQuery access like $.jGrowl(...) or jQuery.jGrowl(...) or in your case, jQuery.toggleVisibility():

interface JQueryStatic {

    ajaxSettings: any;

    jGrowl(object?, f?): JQuery;

}

And for your own custom made functions you use using jQuery.fn.extend, use the JQuery interface:

interface JQuery {

    fileinput(object?): void;//custom jquery plugin, had no typings

    enable(): JQuery;

    disable(): JQuery;

    check(): JQuery;

    select_custom(): JQuery;

}

Optional, here are my extended JQuery functions:

jQuery.fn.extend({
    disable: function () {
        return this.each(function () {
            this.disabled = true;
        });
    },
    enable: function () {
        return this.each(function () {
            this.disabled = false;
        });
    },
    check: function (checked) {
        if (checked) {
            $(this).parent().addClass('checked');
        } else {
            $(this).parent().removeClass('checked');
        }
        return this.prop('checked', checked);
    },
    select_custom: function (value) {
        $(this).find('.dropdown-menu li').each(function () {
            if ($(this).attr('value') == value) {
                $(this).click();
                return;
            }
        });
    }
});

Upvotes: 11

Related Questions