The problem
So you have learned TypeScript but there is no escape from jQuery. It's crawling back over and over again from the dungeons. But you'd like to write your code in TypeScript and this damn thing doesn't know your new cool method? Want to teach it a lesson? Read on!
The stage
TypeScript is great! No question about it. I use it primarily with webpack and it is a wonderful combination. One of the best things it has is the ability to merge interface definitions. That's right! You can literally extend the interface as you wish! This will come very handy when adding new methods to be called in a jQuery chain. First let's define a plugin foo
in plain JavaScript.
import * as $ from 'jquery'
$.fn.foo = function () {
return this.each(function() {
$(this).css({ 'background-color': 'blue' })
})
}
Nothing fancy, right? Each element passed on will receive a blue background. I love blue that is why it is blue and not red.
The solution
Now for the tricky part: teaching TypeScript the definitions. I say definitions because we'll teach it first the JQuery interface by installing the @typings/jquery
package
$ npm install --save-dev '@types/jquery'
Now if you're like me and you use jQuery 3 or later with the default TypeScript configuration you will see a message saying something about Iterable
. That's easy to fix. In the tsconfig.json
make sure you have the lib
line containing the es2015.iterable
element, like so:
"compilerOptions": {
"lib" : [ "es2015", "es2015.iterable", "dom" ]
}
With that out of the way let's teach TypeScript the new foo
declare global {
interface JQuery {
foo (): JQuery
}
}
This is called declaration merging and allows for arbitrary declarations to be added to arbitrary interfaces just like in JavaScript you can add arbitrary fields to arbitrary objects. Cool, ain't it?
Also note that we use the global
module. That's because if we're inside of another module then the original JQuery
interface is a different one from the one defined in the global scope and things just don't go so well in that case.
Now let's use our new toy:
$('div').foo()
Don't forget the new way of importing jQuery requires the allowSyntheticDefaultImports
compiler option.
Happy coding!
No comments:
Post a Comment