TypeScript 入门指南:必要性、优势与实战配置

作者:知秋

时间:2026-10-26

浏览:664

本文深入解析 TypeScript 在前端开发中的必要性,阐述其类型系统带来的编译期错误检查、编辑器智能提示及代码可维护性优势。同时提供从环境搭建、tsconfig.json 配置到 Webpack 集成的完整实战指南,帮助开发者快速上手 TypeScript。

文章目录

TypeScript 与 JavaScript 代码具有极高的兼容性,迁移成本极低,直接将 JS 代码重命名为 TS 即可运行。对于未接触过强类型语言的开发人员而言,可能会担心定义类型和新概念会增加学习负担。但 TypeScript 并不会脱离 JavaScript 成为独立语言,其核心学习点在于掌握其类型系统。

什么是 TypeScript

TypeScript 是由微软推出的 JavaScript 超集语言。作为 JavaScript 的严格超集,所有合法的 JavaScript 代码均符合 TypeScript 规范,这类似于 C 与 Objective-C 的关系。TypeScript 为 JavaScript 引入了强大的类型系统以及对 ES2015 标准的支持,其编译工具可部署于任何服务器或任务系统中。

自 ES2015 发布以来,JavaScript 取得了显著进步。然而,随着设备性能提升及 JavaScript 在应用层地位的重要性日益凸显,大型项目对语言级别的支持需求愈发强烈。微软发现,外部客户在开发大规模 JavaScript 应用时,常受限于语言本身的短板,这促使了 TypeScript 的诞生。

类型系统不仅是良好的文档形式,还能增强编辑器在 智能提示、跳转定义 以及 代码补全 等方面的功能。它能在编译阶段捕获大部分错误,对大型工程的代码可读性和可维护性具有显著作用。

TypeScript 的流行趋势

TypeScript 拥有活跃的社区生态,大部分第三方库都提供了 TypeScript 类型定义文件,甚至知名前端库如 Google 的 Angular 已完全使用 TypeScript 开发。我们可以通过相关数据观察其流行趋势:

什么是 TypeScript

TypeScript 的优势和收益是什么

虽然 TypeScript 官网列出了诸多优势,但此处尝试进行总结:

  • 类型系统可在编译阶段发现大部分错误
  • 类型系统也是直观的编程文档,可清晰查看任何函数或 API 的输入输出类型
  • 类型系统增强了编辑器或 IDE 的功能
  • TypeScript 支持自动类型推导
  • 所有 JavaScript 代码均为合法的 TypeScript,降低了使用门槛
  • TypeScript 积极拥抱 ES2015 及 ESNext 草案规范
  • 几乎所有第三方库都提供了 TypeScript 类型定义文件

对于需要长期维护的工程,类型系统在可读性和可维护性上展现出比 JavaScript 更强的能力。在良好的编程语境和稳定工具链的辅助下,TypeScript 堪称目前最佳的选择之一。

当然,TypeScript 也存在一定的学习成本,例如 Interfaces、Generics、Enums 等前端工程师可能不熟悉的概念,短期内会增加开发成本。集成和构建库时也需要一定工作量。例如使用 React 开发前端工程时,需进行相关配置,也可直接使用 create-react-app 创建 TypeScript + React 工程。

TypeScript 与 JavaScript 对比表格

| 对比项目 | TypeScript | JavaScript | 注意 | 
| --------| --- | --- | --- | 
| 基本类型 |  boolean number string Array Tuple Enum any void null undefined never object | string number boolean null undefined symbol | TypeScript 中 object 表示的是不是 JavaScript 基本类型的类型| 
| 变量声明 | let const var| let const var | 基本一致 | 
| 接口 | interface | 无 |  TypeScript 的核心是类型检查,因此接口充当了命名这些类型的角色 | 
| 类 | class abstract class  readonly … | class 无 abstract class | 基本一致,但不同的可能发生在未来,TypeScript 使用 private 来定义私有,而 JavaScript 未来极有可能将 #.xx 来定义私有写入标准。TypeScript  支持抽象类,只读等等。| 
| 函数 | N | N | 基本一致,参数赋默认值,剩余参数等等,唯一不同的是 TypeScript 支持?可选参数 | 
| 泛型 | Generics | 无 | 泛型是一个特别灵活的可重用指定不同类型来控制具体类型的类型,TypeScript 支持 | 
| 枚举 | Enums | 无 | TypeScript 支持的枚举不仅可以默认从 0 开始,也可以赋值具体的字符串,它的操作空间非常大 | 
| 类型推断 | 支持 | 无 |  let x = 3; TypeScript 可以通过 3 来推断 x 的类型是 number | 
| 高阶类型 | & typeof  instanceof … | 无 | TypeScript 独有 | 
| Symbols | N | N | Symbol 一样 | 
| 迭代器 | N | N | 如果实现了 Symbol.iterator ,那么就被视为可迭代的,术语上和 JavaScript 定义的一样 | 
| Generators | N | N | 一样 |
| 模块系统 | N | export import | 事实上 TypeScript 支持多种多样的模块系统,既有 ESModule 也有 Commonjs 规范,甚至还有 AMD UMD 等 |
| 其他 | N | N | 由于 TypeScript 是 JavaScript 的超集,因此 ES2016 之后以及 ESNext 定义的  api 都可以直接在 TypeScript 中使用 并不需要语言支持,至于其他一些比如 JSX Mixins 等等,由于这些不属于 JavaScript 标准因此这里不再复述 。|

环境配置

TypeScript 3.3

鉴于 TypeScript 需要编译,我们必须使用编译工具。在正式学习前,需先安装编译环境。

  • 安装 Node.js 10.15.3 LTS
  • 安装 typescript
$ npm install -g typescript
$ tsc --version

国际惯例 Hello World

创建一个 helloworld.ts 文件,然后输入:

let helloworld = "";

console.log(helloworld);
$ tsc helloworld.ts

现在稍微改动一行代码,在 JavaScript 中完全可以这样写:

let helloworld = "";

helloworld = 1;

从语法角度看这完全正确,但语句未锁定类型,某些情况下易出现未知异常。现在执行 tsc 来编译它:

$ tsc helloworld.ts
helloworld.ts:5:1 - error TS2322: Type '1' is not assignable to type 'string'.

5 helloworld = 1;

Found 1 error.

编译器明确提示不能将 1 赋值给字符串类型,这正是 TypeScript 带来的优势。

tsconfig.json

tsconfig.json 文件用于指定编译 TypeScript 项目所需的根目录及编译器选项。若工程中存在 tsconfig.json,则表明 tsconfig.json 所在目录为 TypeScript 工程的根目录。

使用 tsconfig.json 的规则如下:

  • 若直接运行 tsc,编译器将从当前目录开始搜索 tsconfig.json 并向上查找
  • 也可直接运行 tsc -p xxx,此时 xxx 目录上必须存在 tsconfig.json 文件
  • 若在命令行直接输出文件 tsc helloworld.ts,编译器将忽略 tsconfig.json 文件

当然,也可直接使用 tsc --init 在当前运行目录中创建一个 tsconfig.json(推荐)。

{
  "compilerOptions": {
    /* Basic Options */
    "target": "es5",                          /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
    "module": "commonjs",                     /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
    // "lib": [],                             /* 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": "./",                        /* 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 */
    // "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. */
  }
}

编译器选项

这些编译器选项也是 tsconfig.json 中的配置项

若不想通过 tsconfig.json 配置编译器,也可使用如下命令行选项执行编译任务。此处仅介绍常用选项,其他配置请参考 Compiler Options 表格。

  • --watch 或 -w 监视输入文件的更改并触发重新编译
  • --version 或 -v 查看编译器的版本
  • --types=["字符串"] 类型描述文件的名称列表
  • --target="" 指定编译的 ECMAScript 的版本,默认版本是 ES3
  • --strict 启用所有严格类型检查
  • --sourceMap 生成对应的 .map 文件
  • --outFile 输出到单个文件
  • --outDir 输出到目录
  • --module 或 -m 指定使用哪种模块标准来输出代码,选项有 "None", "CommonJS", "AMD", "System", "UMD", "ES6", "ES2015" or "ESNext"
  • --lib 要包含在编译中的库文件列表,比如 ES2015.Promise
  • --jsx 在 .tsx 文件中支持 JSX 可指定要编译输出的 JSX 类型

与 Webpack 集成

实际上,我们不会单独使用 TypeScript,而是将其融入现有技术栈和工具中。目前多数前端工程将 Webpack 视为标准配置,因此 TypeScript 编译器与 Webpack 的集成非常有用。

awesome-typescript-loader 是 TypeScript 提供的在 Webpack 中使用的 loader,因此我们只需要:

$ yarn add typescript awesome-typescript-loader source-map-loader --dev

然后在你的 webpack.config.json 文件中配置即可:

var fs = require('fs')
var path = require('path')
var webpack = require('webpack')
const { CheckerPlugin } = require('awesome-typescript-loader');
var ROOT = path.resolve(__dirname)

module.exports = {
  entry: './src/index.tsx',
  devtool: 'inline-source-map',
  output: {
    path: ROOT + '/dist',
    filename: '[name].bundle.js',
    sourceMapFilename: '[name].bundle.map.js',
    publicPath: '//localhost:8889/dist/',
  },
  devServer: {
    inline: true,
    quiet: true,
    contentBase: "./",
    port: 8889
  },
  module: {
    rules: [
      { test: /\.ts[x]?$/, loader: "awesome-typescript-loader" },
      { enforce: "pre", test: /\.ts[x]$/, loader: "source-map-loader" },
    ]
  },
  resolve: {
    extensions: [".ts", ".tsx"],
    alias: {
      '@': path.resolve(ROOT,'src')
    }
  },
  plugins: [
    new CheckerPlugin(),
  ]
}

结语

本文简要介绍了如何学习 TypeScript。古语云:了解历史才能真正了解故事。时代变迁中,JavaScript 是目前唯一实现 Write Once Run Anywhere 的脚本语言(尽管 C 语言也具备此特性),其热度长久不衰。但 JavaScript 本身存在缺陷,未来新标准或许会逐步弥补。至少现在,让我们用 TypeScript 来解决你可能面临的问题。

到此这篇关于 typescript 难学吗?前端有必要学?该怎么学 typescript 的文章就介绍到这了,更多相关前端学 typescript 内容请搜索本站以前的文章或继续浏览下面的相关文章,希望大家以后多多支持本站!

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章