57

基于 TypeScript 开发 NPM 模块

 5 years ago
source link: https://www.tuicool.com/articles/QrIv2if
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

初始化 NPM 项目

mkdir project-name
cd project-name
npm init

添加开发基础包

添加 TypeScript

yarn add typescript -D

添加 Jest 测试工具

yarn add jest ts-jest @types/jest -D

添加 @types/node

yarn add @types/node -D

初始化 TypeScript 配置

./node_modules/.bin/tsc --init

这会在你的项目根目录新建一个 tsconfig.json 文件

现在的目录结构如下:

.
├── node_modules
├── package.json
├── tsconfig.json
└── yarn.lock

文件解析

tsconfig.json

这是 TypeScript 的配置文件,默认仅启用了几项,我一般的配置如下:

{
  "compilerOptions": {
    /* Basic Options */
    "target": "es5" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */,
    "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */,
    "lib": [
      "es6"
    ] /* Specify library files to be included in the compilation. */,
    // "allowJs": true,                       /* Allow javascript files to be compiled. */
    // "checkJs": true,                       /* Report errors in .js files. */
    // "jsx": "preserve",                     /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
    "declaration": true /* Generates corresponding '.d.ts' file. */,
    "declarationMap": true /* Generates a sourcemap for each corresponding '.d.ts' file. */,
    // "sourceMap": true,                     /* Generates corresponding '.map' file. */
    // "outFile": "./",                       /* Concatenate and emit output to single file. */
    "outDir": "./dist" /* Redirect output structure to the directory. */,
    // "rootDir": "./",                       /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
    // "composite": true,                     /* Enable project compilation */
    // "incremental": true,                   /* Enable incremental compilation */
    // "tsBuildInfoFile": "./",               /* Specify file to store incremental compilation information */
    // "removeComments": true,                /* Do not emit comments to output. */
    // "noEmit": true,                        /* Do not emit outputs. */
    // "importHelpers": true,                 /* Import emit helpers from 'tslib'. */
    // "downlevelIteration": true,            /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
    // "isolatedModules": true,               /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */

    /* Strict Type-Checking Options */
    "strict": true /* Enable all strict type-checking options. */,
    "noImplicitAny": true /* Raise error on expressions and declarations with an implied 'any' type. */,
    "strictNullChecks": true /* Enable strict null checks. */,
    "strictFunctionTypes": true /* Enable strict checking of function types. */,
    "strictBindCallApply": true /* Enable strict 'bind', 'call', and 'apply' methods on functions. */,
    "strictPropertyInitialization": true /* Enable strict checking of property initialization in classes. */,
    "noImplicitThis": true /* Raise error on 'this' expressions with an implied 'any' type. */,
    "alwaysStrict": true /* Parse in strict mode and emit "use strict" for each source file. */,

    /* Additional Checks */
    "noUnusedLocals": true /* Report errors on unused locals. */,
    "noUnusedParameters": true /* Report errors on unused parameters. */,
    "noImplicitReturns": true /* Report error when not all code paths in function return a value. */,
    "noFallthroughCasesInSwitch": true /* Report errors for fallthrough cases in switch statement. */,

    /* Module Resolution Options */
    // "moduleResolution": "node",            /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
    // "baseUrl": "./",                       /* Base directory to resolve non-absolute module names. */
    // "paths": {},                           /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
    // "rootDirs": [],                        /* List of root folders whose combined content represents the structure of the project at runtime. */
    // "typeRoots": [],                       /* List of folders to include type definitions from. */
    // "types": [],                           /* Type declaration files to be included in compilation. */
    // "allowSyntheticDefaultImports": true,  /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
    "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
    // "preserveSymlinks": true,              /* Do not resolve the real path of symlinks. */

    /* Source Map Options */
    // "sourceRoot": "",                      /* Specify the location where debugger should locate TypeScript files instead of source locations. */
    // "mapRoot": "",                         /* Specify the location where debugger should locate map files instead of generated locations. */
    // "inlineSourceMap": true,               /* Emit a single file with source maps instead of having a separate file. */
    // "inlineSources": true,                 /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */

    /* Experimental Options */
    // "experimentalDecorators": true,        /* Enables experimental support for ES7 decorators. */
    // "emitDecoratorMetadata": true,         /* Enables experimental support for emitting type metadata for decorators. */
  },
  "include": ["./src/**/*"],
  "exclude": ["node_modules", "src/__tests__"]
}

package.json

添加了几条 scripts

{
  "name": "project-name",
  "version": "0.0.0-development",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "rm -rf ./dist && tsc",
    "watch": "yarn test --watch",
    "setup": "yarn install && npx npm-install-peers",
    "test": "jest"
  },
  "author": "",
  "license": "SEE LICENSE IN LICENSE FILE",
  "devDependencies": {
    "@types/jest": "^24.0.13",
    "@types/node": "^12.0.3",
    "jest": "^24.8.0",
    "ts-jest": "^24.0.2",
    "typescript": "^3.4.5"
  }
}

添加 jest.config.js 文件

内容如下:

module.exports = {
  // We always recommend having all TypeScript files in a src folder in your project. We assume this is true and specify this using the roots option.
  roots: ["<rootDir>/src"],
  transform: {
    "^.+\\.tsx?$": "ts-jest" //The transform config just tells jest to use ts-jest for ts / tsx files.
  }
};

添加 .gitignore 文件

该文件告诉 git 哪些文件不需要跟踪

# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# nyc test coverage
.nyc_output

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# TypeScript v1 declaration files
typings/

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env

# next.js build output
.next

# map
*.map

# gitbook
_book

初始化 git 项目

git init

jest watch 需要有 git 环境才能运行

添加 src/index.ts 文件

内容如下:

export const sum = (a: number, b: number): number => a + b;

添加 src/__tests__

按我们的 jest 测试用例: src/__tests__/index.test.ts ,内容如下:

import { sum } from "..";

test("sum", () => {
  expect(sum(1, 2)).toBe(3);
});

开始开发

yarn jest

此时终端显示如下信息:

PASS  src/__tests__/index.test.ts
  ✓ sum (15ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        2.133s
Ran all test suites related to changed files.

Watch Usage
 › Press a to run all tests.
 › Press f to run only failed tests.
 › Press p to filter by a filename regex pattern.
 › Press t to filter by a test name regex pattern.
 › Press q to quit watch mode.
 › Press Enter to trigger a test run.

现在修改一下 index.ts ,文件内容改为下面这样:

export const sum = (a: number, b: number): number => a + b;

export const multiply = (a: number, b: number): number => a * b;

再修改 __tests__/index.test.ts ,内容如下:

import { sum, multiply } from "..";

test("sum", () => {
  expect(sum(1, 2)).toBe(3);
});

test("multiply", () => {
  expect(multiply(2, 3)).toBe(6);
});

会发现终端会自动测试你的代码:

PASS  src/__tests__/index.test.ts
  ✓ sum (4ms)
  ✓ multiply

Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        4.164s
Ran all test suites related to changed files.

完整的代码可以在下面看到:


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK