首页 > 解决方案 > Importing JavaScript files in Typescript, unable to access functions in TS, able to access them in html

问题描述

I recently started integrating TypeScript and React with my companies legacy JavaScript code base. It's been very hit and miss, as I'm sure many of you understand.

After overcoming many of the big hurdles such as setting up a proper webpack process, understanding and setting up tsconfig files and breaking up the bundling properly, I've finally integrated it all with our current CI-pipeline.

However, now I'm having an issue with importing JavaScript libraries in my TypeScript code. I know it's bad practice, but it's sort of a middle-hand before moving to becoming fully TS-compliant.

I've got this basic component which builds fine:

import * as React from "react";
import * as ReactDOM from "react-dom";
import { Header } from "./components/header";
import * as $C from "./../../fortress.content.js";
import * as $F from "./../../fortress.js"; 

let url : string  = $F.writeUrl("Account", "LoginAjax");

ReactDOM.render(
    <div>
        <div> {url} </div>
    </div>,  
    document.getElementById("body")
);

$F.writeUrl allows us to essentially create a string based on a webconfig file in the root of the project, so basically a function taking a few different parameters and returning a string based on it:

However, when I run the transpiled JavaScript in a baremetal html file:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<div id="body"></div>
<div id="header"></div>
<body> 
    <script src="js/jquery-2.1.4.min.js"></script> 
    <script src="js/react-0.14.3.js"></script>
    <script src="js/react-dom-0.14.3.js"></script> 
    <script src="js/filemanager/filemanager.bundle.js"></script>
    <script src="js/anothermanager/anothermanager.bundle.js"></script>
    <script>  
            console.log("$F: ", $F);
            console.log("$C: ", $C);
    </script>
</body>
</html>

I get these errors:

Uncaught TypeError: Cannot read property 'bind' of undefined
    at new t (filemanager.bundle.js:1)
    at ReactCompositeComponentWrapper.mountComponent (react.js:5504)
    at ReactCompositeComponentWrapper.wrapper [as mountComponent] (react.js:12346)
    at Object.mountComponent (react.js:12971)
    at ReactDOMComponent.mountChildren (react.js:11685)
    at ReactDOMComponent._createContentMarkup (react.js:6817)

anothermanager.bundle.js:1 Uncaught ReferenceError: $C is not defined
    at anothermanager.bundle.js:1
    at Object.<anonymous> (anothermanager.bundle.js:1)
    at n (anothermanager.bundle.js:1)
    at Object.<anonymous> (anothermanager.bundle.js:1)
    at n (anothermanager.bundle.js:1)
    at anothermanager.bundle.js:1
    at anothermanager.bundle.js:1
    at ReactDOMComponent.mountComponent (react.js:6705)
    at Object.mountComponent (react.js:12971)
    at ReactCompositeComponentWrapper.mountComponent (react.js:5581)
    at ReactCompositeComponentWrapper.wrapper [as mountComponent] (react.js:12346)

index.html:17 Uncaught ReferenceError: $F is not defined
    at index.html:17

So I tried changing this to instantiate $C and $F in my TS:

let test = $F;
let test2 = $C;

This removed the above errors and actually shows me the $F and $C objects in my console log. But the problem now is that the $F.writeUrl("Account", "LoginAjax") is blowing as Chrome won't recognise it as a "function".

Have I done anything wrong with my imports?

标签: javascripttypescript

解决方案


我猜你不需要import反应包中的那些文件。如果这些文件不使用module.exportsor导出任何内容export,而只是设置window成员以供以后使用(这实际上是几年前的标准),据我所知您应该:

1) 将这些文件加载​​为脚本,以便它们随处可用。请务必在任何react相关脚本/捆绑包之前添加它们,这样您就可以确定它们在安装反应代码时可用:

<script src="js/jquery-2.1.4.min.js"></script>
<script src="js/path-to-fortress-content.js"></script>
<script src="js/path-to-fortress.js"></script> 
<script src="js/react-0.14.3.js"></script>
<script src="js/react-dom-0.14.3.js"></script>

2)现在,它们在您的反应代码中可用。您需要使用它们window来让您的捆绑器处理 $F/$C 模块:

let $f: any = (window as any).$F;
let url : string  = $F.writeUrl("Account", "LoginAjax");

推荐阅读