安装TypeScript
有两种主要的方式来获取TypeScript工具:
- 通过npm(Node.js包管理器)
- 安装Visual Studio的TypeScript插件
TypeScript 的安装很简单,你可以通过npm直接在全局安装 TypeScript。
npm install -g typescript
npm的服务器在国外,访问比较慢,可以更换成国内源:
npm config set registry https://registry.npm.taobao.org
当然也可以安装cnpm(采用的国内源),使用时需要npm命令的地方都换成cnpm
npm install -g cnpm --registry=https://registry.npm.taobao.org
创建环境
我们创建一个目录并且进入该目录
mkdir ts-study && cd ts-study
接着创建src目录
mkdir src
在src下面创建index.ts,也可以手动创建
touch src/index.ts
以上两个的合并命令是
mkdir src && touch src/index.ts
接下来目录初始化
npm init
我们要使用TypeScript 的话通常也需要初始化:
tsc --init
这个时候你会发现目录下多了一个tsconfig.json文件.
这是 TypeScript 的配置文件,里面已经包含官方初始化的一些配置以及注释,我们现在进行自定义的配置:
{
"compilerOptions": {
"target": "es5", // 指定 ECMAScript 目标版本: 'ES5'
"module": "commonjs", // 指定使用模块: 'commonjs', 'amd', 'system', 'umd' or 'es2015'
"moduleResolution": "node", // 选择模块解析策略
"experimentalDecorators": true, // 启用实验性的ES装饰器
"allowSyntheticDefaultImports": true, // 允许从没有设置默认导出的模块中默认导入。
"sourceMap": true, // 把 ts 文件编译成 js 文件的时候,同时生成对应的 map 文件
"strict": true, // 启用所有严格类型检查选项
"noImplicitAny": true, // 在表达式和声明上有隐含的 any类型时报错
"alwaysStrict": true, // 以严格模式检查模块,并在每个文件里加入 'use strict'
"declaration": true, // 生成相应的.d.ts文件
"removeComments": true, // 删除编译后的所有的注释
"noImplicitReturns": true, // 不是函数的所有返回路径都有返回值时报错
"importHelpers": true, // 从 tslib 导入辅助工具函数
"lib": ["es6", "dom"], // 指定要包含在编译中的库文件
"typeRoots": ["node_modules/@types"],
"outDir": "./dist",
"rootDir": "./src"
},
"include": [ // 需要编译的ts文件一个*表示文件匹配**表示忽略文件的深度问题
"./src/**/*.ts"
],
"exclude": [ //部需要编译的文件
"node_modules",
"dist",
"**/*.test.ts",
]
}
完整的tsconfig.json文件好像是这样的:
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig.json to read more about this file */
/* Basic Options */
// "incremental": true, /* 启动增量编译 */
"target": "es5", /* 指定 ECMAScript 目标版本: 'ES3' (默认), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
"module": "commonjs", /* 指定使用模块: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
"lib": ["es6", "dom"], /* 指定要包含在编译中的库文件 */
// "allowJs": true, /* 允许编译 javascript 文件。 */
// "checkJs": true, /* 检查js的错误 */
// "jsx": "preserve", /* 指定 JSX 代码生成: 'preserve', 'react-native', or 'react'. */
"declaration": true, /* 生成相应的.d.ts文件 */
// "declarationMap": true, /* 为每个源图生生成相应的.d.ts文件 */
"sourceMap": true, /* 把 ts 文件编译成 js 文件的时候,同时生成对应的 map 文件*/
// "outFile": "./", /* 串联并输出到单个文件。 */
"outDir": "./dist", /* 将输出结构重定向到目录。 */
"rootDir": "./src", /* 指定输入文件的根目录。用于使用 -outDir 控制输出目录结构。 */
// "composite": true, /* 启用项目编译 */
// "tsBuildInfoFile": "./", /* 指定文件以增量存储编译信息 */
"removeComments": true, /* 删除编译后的所有的注释 */
// "noEmit": true, /* Do not emit outputs. */
"importHelpers": true, /* 从 tslib 导入辅助工具函数 */
// "downlevelIteration": true, /* 在定位"ES5"或"ES3"时,对"for-of"、传播和销毁中的可操作数据提供完全支持。*/
// "isolatedModules": true, /* 将每个文件作为单独的模块转堆(类似于 'ts)。转位模块')。 */
/* Strict Type-Checking Options */
"strict": true, /* 启用所有严格类型检查选项 */
"noImplicitAny": true, /* 在表达式和声明上有隐含的 any类型时报错 */
// "strictNullChecks": true, /* 启用严格的空检查。 */
// "strictFunctionTypes": true, /* 启用对函数类型的严格检查。 */
// "strictBindCallApply": true, /* 在函数上启用严格的"bind"、"call"和"apply"方法。 */
// "strictPropertyInitialization": true, /* 启用对类中属性初始化的严格检查。 */
// "noImplicitThis": true, /* 在"this"表达式上引发与隐含的"任何"类型的错误。 */
"alwaysStrict": true, /* 以严格模式检查模块,并在每个文件里加入 'use strict' */
/* Additional Checks */
// "noUnusedLocals": true, /* 报告未使用局部变量的错误。 */
// "noUnusedParameters": true, /* 报告未使用参数的错误。 */
"noImplicitReturns": true, /* 不是函数的所有返回路径都有返回值时报错 */
// "noFallthroughCasesInSwitch": true, /* 报告开关语句中掉线情况的错误。*/
/* Module Resolution Options */
"moduleResolution": "node", /* 选择模块解析策略: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
// "baseUrl": "./", /* 用于解析非绝对模块名称的基目录。 */
// "paths": {}, /* 将导入重新映射到相对于"baseUrl"的位置的一系列条目。 */
// "rootDirs": [], /* */
"typeRoots": ["node_modules/@types"], /* 其组合内容在运行时表示项目结构的根文件夹列表。 */
// "types": [], /* 键入要包含在编译中的声明文件。*/
"allowSyntheticDefaultImports": true, /* 允许从没有设置默认导出的模块中默认导入 */
"esModuleInterop": true, /* 通过创建所有导入的命名空间对象,实现 CommonJS 和 ES 模块之间的发出互操作性。暗示 "允许合成默认"。 */
// "preserveSymlinks": true, /* 不要解析符号链接的真实路径。 */
// "allowUmdGlobalAccess": true, /* 允许从模块全局访问 UMD 。 */
/* Source Map Options */
// "sourceRoot": "", /* 指定调试器应查找 TypeScript 文件的位置,而不是源位置。 */
// "mapRoot": "", /* 指定调试器应查找地图文件的位置,而不是生成的位置。*/
// "inlineSourceMap": true, /* 使用源映射发出单个文件,而不是具有单独的文件。 */
// "inlineSources": true, /* 在单个文件中将源与源映射一起发出;需要设置 "- - 内联源地图" 或 "- - 源映射" 。 */
/* Experimental Options */
"experimentalDecorators": true, /* 启用实验性的ES装饰器 */
// "emitDecoratorMetadata": true, /* 支持为修饰器发出类型元数据的实验支持。*/
/* Advanced Options */
"skipLibCheck": true, /* 跳过声明文件的类型检查。*/
"forceConsistentCasingInFileNames": true /* 不允许对同一文件的不一致引用。 */
},
"include": [ // 需要编译的ts文件一个*表示文件匹配**表示忽略文件的深度问题
"./src/**/*.ts"
],
"exclude": [
"node_modules",
"dist",
"**/*.test.ts",
]
}
然后在package.json中加入我们的script命令:
{
"name": "ts-study",
"version": "1.0.0",
"description": "",
"main": "src/index.ts",
"scripts": {
"build": "tsc", // 编译
"build:w": "tsc -w" // 监听文件,有变动即编译
},
"author": "",
"license": "ISC",
"devDependencies": {
"typescript ": "^3.6.4"
}
}
编写第一个 TypeScript 程序
在src/index.ts中输入以下代码:
function greeter(person) {
return "Hello, " + person
}
const user = "Jane User";
这个时候你会看到一个警告,这个警告在官方默认配置中是不会出现的,正是由于我们开启了 noImplicitAny 选项,对于隐式含有 any 类型的参数或者变量进行警告⚠️.
之所以一开始就开启严格模式,是因为一旦你开始放任any类型的泛滥,就会把 TypeScript 变成 AnyScript ,会很难改掉这个恶习,所以从一开始就要用规范的 TypeScript 编码习惯。
我们进行修改如下:
function greeter(person: string) {
return "Hello, " + person;
}
此时我们可以看到,greeter函数自动加上了返回值类型,这是 TypeScript 自带的_类型推导_。
接下来我们编译这个index.ts
tsc src/index.ts
输出一个index.js的文件它包含了和输入文件中相同的JavsScript代码。
如图
接下来我们写一个完整的示例,并运行它
index.ts
/* 创建一个 Student类 */
class Student {
fullName: string;
constructor(public firstName: string, public middleInitial: string, public lastName: string) {
this.fullName = firstName + " " + middleInitial + " " + lastName;
}
}
/* 创建一个 Person 接口 */
interface Person {
firstName: string;
lastName: string;
}
function greeter(person : Person) {
return "Hello, " + person.firstName + " " + person.lastName;
}
let user = new Student("Jane", "M.", "User");
document.body.innerHTML = greeter(user);
然后我们能编译这个ts
tsc src/index.ts
编译后生成的index.js文件如下:
/* 创建一个 Student类 */
var Student = /** @class */ (function () {
function Student(firstName, middleInitial, lastName) {
this.firstName = firstName;
this.middleInitial = middleInitial;
this.lastName = lastName;
this.fullName = firstName + " " + middleInitial + " " + lastName;
}
return Student;
}());
function greeter(person) {
return "Hello, " + person.firstName + " " + person.lastName;
}
var user = new Student("Jane", "M.", "User");
document.body.innerHTML = greeter(user);
然后我们新建一个index.html文件,代码如下:
<!DOCTYPE html>
<html>
<head><title>TypeScript Greeter</title></head>
<body>
<script src="index.js"></script>
</body>
</html>
最后我们在浏览器中打开index.html,浏览器显示如下
到此我们就完整的运行了一个ts的实例了
ts-node 的安装和使用
我们接着上面的index.ts,我们改写下,改成来打印greeter(user);
/* 创建一个 Student类 */
class Student {
fullName: string;
constructor(public firstName: string, public middleInitial: string, public lastName: string) {
this.fullName = firstName + " " + middleInitial + " " + lastName;
}
}
/* 创建一个 Person 接口 */
interface Person {
firstName: string;
lastName: string;
}
function greeter(person : Person) {
return "Hello, " + person.firstName + " " + person.lastName;
}
let user = new Student("Jane", "M.", "User");
console.log(greeter(user));
然后同样的编译成js
tsc src/index.ts
编译后生成的index.js文件如下:
/* 创建一个 Student类 */
var Student = /** @class */ (function () {
function Student(firstName, middleInitial, lastName) {
this.firstName = firstName;
this.middleInitial = middleInitial;
this.lastName = lastName;
this.fullName = firstName + " " + middleInitial + " " + lastName;
}
return Student;
}());
function greeter(person) {
return "Hello, " + person.firstName + " " + person.lastName;
}
var user = new Student("Jane", "M.", "User");
console.log(greeter(user));
然后我们运行该js
node src/index.js
在控制台就会直接打印如下结果:
是不是觉得要运行ts,要先转换成js,再运行js文件,这样效率太低了。
我们可以使用ts-node这个插件来解决这个问题,用这个插件后,就不回编译这么麻烦了,直接使用ts-node就可以看到编译结果了。
首先我们使用npm/cnpm命令来全局安装ts-node
npm install -g ts-node
安装完成后,可以编译index.ts了
ts-node src/index.ts
控制台就会直接打印结果了