TypeScript – Work with JavaScript Library


前言

JavaScript 早期是没有 Modular 和 Type (类型) 的. 随着这几年的普及, 几乎有维护的 Library 都有 Modular 和 Type 了.

但万一遇到没有 Modular 或者 Type 的 LIbrary 时, 要如何 import 和类型安全的调用它们呢? 

这篇就是要讲讲这些麻烦事儿. 以前做 Angular 开发的时候也写过一篇相关的, 但那篇是基于 Angular 的, 这篇则底层一点, 只用了 TypeScript 和 SystemJS

请先阅读 , 本篇将基于它的基础作为例子.

搭环境

Follow 回这篇  的例子.

改一下它的 folder 结构. 全部放外面有点乱

index.html

DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Documenttitle>
    
    <script
      src="https://cdn.jsdelivr.net/npm/systemjs@6.12.1/dist/s.min.js"
      defer
    >script>
    <script
      src="https://cdn.jsdelivr.net/npm/systemjs@6.12.1/dist/extras/named-register.min.js"
      defer
    >script>
    <script
      src="https://cdn.jsdelivr.net/npm/systemjs@6.12.1/dist/extras/amd.min.js"
      defer
    >script>
    <script
      src="https://cdn.jsdelivr.net/npm/systemjs@6.12.1/dist/extras/amd.min.js"
      defer
    >script>

    
    <script type="systemjs-importmap">
      {
        "imports": {
          "lodash": "https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js",
          "jquery": "https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"
        }
      }
    script>

    
    <script type="systemjs-module" src="../dist/bundle.js">script>
  head>
  <body>
    <h1>Hello Worldh1>
  body>
html>

index.ts

import { myModuleFunction } from './my-module';

myModuleFunction();

my-module.ts

import $ from 'jquery';
import _ from 'lodash';

export function myModuleFunction() {
  $('h1').css('color', 'blue');
  _.forEach([1, 2, 3], (index) => $('body').append($(`

${index}

`))); }

tsconfig.json

{
  "compilerOptions": {
    "target": "es2016",
    "module": "System",
    "rootDir": "./src",
    "outFile": "./dist/bundle.js",
    "outDir": "./dist",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  }
}

Import Local JavaScript Library

默认配置下, TypeScript 不允许直接 import .js 文件.

local-js-library.js

export function localJsLibraryFunction(age) {
  return age;
}

index.ts

直接报错

tsconfig.json 

{
  "compilerOptions": {
    "allowJs": true
  }
}

开启 allowJs 就不会报错了

import { localJsLibraryFunction } from './local-js-library.js';
console.log('localJsLibraryFunction', localJsLibraryFunction(11));

虽然成功 import 到了, 但是会发现它有许多的 any 接口

如果想要有一点点类型, 但又不想搞 .d.ts 的话, 可以开启 checkJs

{
  "compilerOptions": {
    "allowJs": true,
    "checkJs": true
  }
}

这时会发现 local-js-module.js 报错了

它需要通过注释声明类型

/**
 * @param {number} age
 */
export function localJsLibraryFunction(age) {
  return age;
}

这样 index.ts 就看的见类型了

注意坑

如果这时, 你把 import 删掉 > tsc > run LIve Server

你会发现跑不了, 虽然没有 import 了, 但是 bundle.js 依然会有 System.register local-js-library, 而这个就会让它坏掉了, 把这段注释掉就正常

没有去研究为什么, 我觉得用 allowJs 本身就不太顺风水, 强烈建议用 .d.ts 的方案. 

Import no modular and no type JavaScript library

这种 Library 通常已经没用人维护了. 它的使用方式往往是叫你在 html 放