Search code examples
typescriptwebpacktypescript-typingsjsrenderjsviews

Error looking up method on jsrender, using jsrender / jsviews with typescript


I am trying to integrate/use jsview/jsrender in a typescript project with build done using webpack-4. Since the jsrender/jsviews package installed via npm does not contain type definitions not are they available via DefinitelyTyped but the author(s) of jsview/jsrender have provided the type definitions separately. I saved them in typings/[jsrender, jsview] folders and modified my tsconfig.json as shown below:

My tsconfig.json has the following:

{
"compileOnSave": true,
"compilerOptions": {
    "baseUrl": ".",
    "noImplicitAny": true,
    "removeComments": true,
    "preserveConstEnums": true,
    "sourceMap": true,
    "target": "es2015",
    "moduleResolution": "node",
    "declaration": false
},
"include": [
    "static/js/**/*",
    "*/static/ts/**/*.ts"
],
"exclude": [
    "node_modules",
    "**/*.spec.ts"
],
"files": [
    "./typings/jsrender/index.d.ts",
    "./typings/jsviews/index.d.ts"
]

}

And I import jsrender with:

import * as jsrender from 'jsrender'; 

And when I try to use jsrender with:

tmpl = jsrender($).templates('Name: {{:name}}');

The webpack complains with the following error:

TS2339: Property 'templates' does not exist on type 'JQuery'.

The first few lines of type definitions for jsrender has the following:

/// <reference types="jquery" />

declare module 'jsrender' {
    export = jsrender;
}

declare const jsrender: JQueryStatic;

interface JQueryStatic {
    /* var htmlString = $.render.templateName(data, myHelpersObject); // Render named template */
    render: {
        [tmplName: string]: JsViews.TemplateRender;
    };

    /* $.views.xxx ... // JsRender/JsViews APIs */
    views: JsViews.Views;

    /* $.templates(...) or $.templates.templateName: Compile/get template */
    templates: JsViews.Templates;
}

I am not sure why does webpack complain even though when debugging, if I just do:

let tmpl = jsrender($);

and put a breakpoint on the line above, I can see that the tmpl object does have the "templates" function available.

I am not sure if it is a webpack issue, tsconfig issue or the way I am using jsrender.


Solution

  • You are right, those versions of JsRender index.d.ts and JsViews index.d.ts are not correct, for your webpack + typescript scenario.

    JsRender index.d.ts should start like this:

    declare module 'jsrender' {
        export = jsrender;
    }
    
    declare const jsrender: ((jquery?: JQueryStatic) => JQueryStatic) & JQueryStatic;
    
    // ********************************** JsRender **********************************
    
    interface JQueryStatic {
    ...
    

    and JsViews index.d.ts should start like this:

    declare module 'jsviews' {
        export = jsviews;
    }
    
    declare const jsviews: ((jquery?: JQueryStatic) => JQueryStatic) & JQueryStatic;
    
    // ********************************** JsObservable **********************************
    
    interface JQueryStatic {
    ...
    

    With those changes, things should work correctly.

    Here is how you might code your .ts file, if using JsRender and loading jQuery as a module, rather than globally:

    import * as $ from 'jquery'; 
    import * as jsrender from 'jsrender'; 
    
    jsrender($); // load JsRender jQuery plugin methods
    
    let tmpl = $.templates(...);
    
    // Now use tmpl.render() etc.
    

    In fact jsrender($) returns $, so the above simpler syntax is equivalent to your version, (and in fact does not run up against the typescript declaration error issue you hit).

    If using JsViews, you instead write

    import * as $ from 'jquery'; 
    import * as jsviews from 'jsviews'; 
    
    jsviews($); // load JsRender and JsViews jQuery plugin methods
    
    let tmpl = $.templates(...);
    
    // Now use tmpl.render() and/or tmpl.link() etc.