本文使用TypeScript语言,利用Nodejs中内置的readline模块,从终端读取用户输入并根据用户输入的数字计算相应位置的斐波那契数列值,旨在介绍TypeScript和Nodejs的终端模块的基本用法:

1.项目包文件 package.json

  • 该文件在项目根目录下通过 npm init 命令生成,并根据需要进行修改
  • 注意 start 脚本和 watch-ts 脚本文件,后者用于自动监视ts文件变化并编译,前者用于启动程序
  • 项目根目录下新建 srcdist 两个目录,在src目录下新建 index.ts 文件,作为项目主文件
  1. {
  2. "name": "fibonacci",
  3. "version": "1.0.0",
  4. "description": "use typescript to solve fibonacci problem in three ways",
  5. "main": "dist/index.js",
  6. "scripts": {
  7. "start":"npm run serve",
  8. "test": "echo \"Error: no test specified\" && exit 1",
  9. "watch-ts":"tsc -w",
  10. "serve":"node dist/index.js"
  11. },
  12. "keywords": [
  13. "typescript",
  14. "javascript",
  15. "npm",
  16. "fibonacci",
  17. "yield"
  18. ],
  19. "author": "weizy0219",
  20. "license": "MIT",
  21. "devDependencies": {
  22. "@types/node": "^13.11.1",
  23. "ts-node": "^8.8.2",
  24. "typescript": "^3.8.3"
  25. }
  26. }

2. TypeScript配置文件 tsconfig.json

  • 该文件在根目录下使用tsc —init命令生成,并在此基础上进行修改
  • 在默认的 compilerOptions 之外,新增了include和exclude参数来包含和排除的文件夹
  1. {
  2. "compilerOptions": {
  3. /* Basic Options */
  4. // "incremental": true, /* Enable incremental compilation */
  5. "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
  6. "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
  7. // "lib": [], /* Specify library files to be included in the compilation. */
  8. // "allowJs": true, /* Allow javascript files to be compiled. */
  9. // "checkJs": true, /* Report errors in .js files. */
  10. // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
  11. // "declaration": true, /* Generates corresponding '.d.ts' file. */
  12. // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
  13. "sourceMap": true, /* Generates corresponding '.map' file. */
  14. // "outFile": "./", /* Concatenate and emit output to single file. */
  15. "outDir": "dist", /* Redirect output structure to the directory. */
  16. // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
  17. // "composite": true, /* Enable project compilation */
  18. // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
  19. "removeComments": true, /* Do not emit comments to output. */
  20. // "noEmit": true, /* Do not emit outputs. */
  21. // "importHelpers": true, /* Import emit helpers from 'tslib'. */
  22. // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
  23. // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
  24. /* Strict Type-Checking Options */
  25. "strict": true, /* Enable all strict type-checking options. */
  26. "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
  27. "strictNullChecks": true, /* Enable strict null checks. */
  28. // "strictFunctionTypes": true, /* Enable strict checking of function types. */
  29. // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
  30. // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
  31. "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
  32. // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
  33. /* Additional Checks */
  34. // "noUnusedLocals": true, /* Report errors on unused locals. */
  35. // "noUnusedParameters": true, /* Report errors on unused parameters. */
  36. // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
  37. // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
  38. /* Module Resolution Options */
  39. // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
  40. // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
  41. // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
  42. // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
  43. // "typeRoots": [], /* List of folders to include type definitions from. */
  44. // "types": [], /* Type declaration files to be included in compilation. */
  45. // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
  46. "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
  47. // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
  48. // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
  49. /* Source Map Options */
  50. // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
  51. // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
  52. // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
  53. // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
  54. /* Experimental Options */
  55. // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
  56. // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
  57. /* Advanced Options */
  58. "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
  59. },
  60. "include": [
  61. "src/**/*.ts"
  62. ],
  63. "exclude": [
  64. "node_modules",
  65. "**/*.spec.ts"
  66. ]
  67. }

3. 项目主文件 index.ts

本文件功能简单,未进行模块划分;

  • 实现斐波那契数列可以采用递归、代数等高级方法,本项目为演示方便,采用基本直观的循环方法
  • 注意在typescript中导入 node的commonJS 一般使用类似 import * as readline from 'readline' 来保持程序风格的一致性
  • 程序包含了基本的错误提示和处理功能,对非正整数输入返回错误提示
  1. import * as readline from 'readline';
  2. //利用readline的createInterface方法创建基本的提示符和输入输出
  3. //在命令行输入 quit可以直接退出程序
  4. const rl=readline.createInterface({
  5. input:process.stdin,
  6. output:process.stdout,
  7. prompt:'Input an int>0,"quit" to exit >'
  8. });
  9. //基本的fabonacci数列迭代
  10. const fabonacci=(serial:number):number=>{
  11. let prev1=0; //n-1
  12. let prev2=0; //n-1
  13. let sum=0;
  14. for(let i=1;i<=serial;i++){
  15. if(i===1){
  16. // console.log(`current i=${i}`);
  17. sum=1;
  18. }
  19. if(i===2){
  20. sum=1;
  21. }
  22. if(i===3){
  23. prev1=1;
  24. prev2=1;
  25. sum=prev1+prev2;
  26. }
  27. if(i>3){
  28. prev2=prev1;
  29. prev1=sum;
  30. sum=prev1+prev2;
  31. console.log(`i=${i},prev1=${prev1},prev2=${prev2},sum=${sum}`);
  32. }
  33. }
  34. return sum;
  35. }
  36. //区分和处理用户输入
  37. const inputCase=(line:string):string=>{
  38. switch(line.trim()){
  39. case 'quit':
  40. console.log('system shuting down...');
  41. return 'quit';
  42. default:
  43. let lineNumber=parseInt(line);
  44. if(lineNumber){
  45. console.log(`Hello,your input is ${lineNumber}`);
  46. console.log(`The result is ${fabonacci(lineNumber)}`);
  47. }else{
  48. console.log(`Sorry, input invalid,please check again`);
  49. }
  50. return 'prompt';
  51. }
  52. }
  53. //命令提示符,人机接口
  54. rl.prompt();
  55. rl.on('line',(line)=>{
  56. // switch(line.trim())
  57. let response=inputCase(line);
  58. if(response==='quit'){
  59. rl.close();
  60. }else if(response==='prompt'){
  61. rl.prompt();
  62. }
  63. })

4.项目使用

  • 通过 npm i 安装项目模块包(可能需要全局安装typescript)
  • 进入项目根目录,运行 tsc 编译typescript文件,运行 npm run start 或者 node dist/index.js 启动程序,如果安装了 ts-node 模块,也可以输入 ts-node src/index.ts 直接运行typescript文件而无需编译
  • 按照提示符输入数字,系统会计算并返回相应位置的斐波那契数列值,输入 quit 退出,对于非正整数输入系统会返回错误提示
  • 如果要在项目基础上进行开发,可以输入 npm run watch-ts 启动项目热重载自动编译功能
  • 项目源文件如下:

fibonacci.zip