Search code examples
javascripttypescriptimportknockout.jstsc

How to import KnockOut 4 in TypeScript?


This seems simple because the same code works well in simple JS file and it also has autocompletion for the ko variable's members. I have the following TypeScript code below:

// both of the following import lines result in: `ko` undefined

// import { ko } from "@tko/build.knockout";
import { ko } from "../node_modules/@tko/build.knockout/dist/build.knockout.es6";


alert("test: " + ko);

tsconfig.json

{
    "compilerOptions": {
        "removeComments": true,
        "preserveConstEnums": true,
        "sourceMap": true,
        "outDir": "js",
        "target": "ES3",
        "watch": true,
        "allowJs": true,
        "lib": ["ES5", "DOM"],
        "module": "CommonJS"
    },
    "include": [
        "ts"
    ],
    "exclude": [
        "node_modules"
    ]
}

The test repo is here.

Using the given tsconfig.json file, I cannot import the ko4 package well. I could change some of the things in tsconfig.json but I do not know how to make it compatible with all the used modules in my main project. I chose to use ES6 import syntax because it is future-proof.

I would have used KnockOut v3.5 but it does not work with ES6 import syntax.

I also wish to mention that I use VS Code.

Thank you.

Update 1

(based on the answer from Nenad)

In tsconfig.json I had to set moduleResolution to "Node" (previously it was the default, in my case "classic").

I also had to create a package.json file in the root directory of my project. I thought I had one, but I had just a package-lock.json. After creating the package.json file, I rerun npm i and now VS Code understands the imports. I do not have to put a path to something inside the node_modules directory, I just put the name of the npm module.

I also had to replace KnockoutObservable with ko.Observable and all the other Knockout...-named classes and interfaces used in my project.

The remaining problem is that after I switched to the AMD module system the output file (bundle.js) does not contain all the needed modules, just the main.ts file converted to JS. Probably this is the subject of another question.


Solution

  • If you get knockout version 3 via 'npm' or 'yarn':

    yarn add knockout
    

    All you have to do to import knockout is this:

    import * as ko from "knockout";
    

    This works because in node_modules\knockout folder you have package.json file with this lines (among others):

      "main": "build/output/knockout-latest.js",
      "types": "build/types/knockout.d.ts",
    

    That is how typescript knows how to resolve from "knockout" to specific JavaScript file and also where to pull TypeScript types from. Types are bundled in the package.

    Version 4

    On the other side, if you download version 4: yarn add @tko/build.knockout it contains only:

      "main": "dist/build.knockout.js",
    

    So correct way to import it is still:

    import * as ko from "knockout";
    

    However, you need to find TypeScript definitions separately and add them to the project. As far as I could see, for the version 4 they don't exist in the main GitHub repository.