How to extend JQuery functions in TypeScript
Asked Answered
G

3

22

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

Gwalior answered 3/12, 2016 at 13:29 Comment(2)
It seems your interface JQuery is not merged with the original one. Maybe it should be imported. How have you imported the definitions for jQuery ? With the new @types system?Gylys
@Gylys with tsd install jQuery --save afairGwalior
W
38

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

Watt answered 4/12, 2016 at 10:8 Comment(4)
I'm going to create an issue in TS github, maybe it will be fixed. Thank you for an answer.Gwalior
@AlexZhukovskiy Please give the link to the issue, I'm interested too.Gylys
For those who are struggling to know where to put this file (like myself); this link explains very well.Mulford
Oh thank goodness I found this post. I was starting to grow gray hairs over documenting this API.Fathomless
M
11

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;
            }
        });
    }
});
Moitoso answered 3/11, 2017 at 8:43 Comment(1)
This approach seems to clobber the JQuery declarations for regular functions, like .click() and .parent(). Any idea why?Endres
D
0

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

Danaedanaher answered 12/12, 2023 at 14:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.