TypeScript学习笔记
1、TypeScript简介
1、简介
- typescript是JavaScript的一个超集
- typescript是微软开源的自由和开源的编程语言
- 可以编译成纯JavaScript
2、与JavaScript的区别
扩展了JavaScript的语法,typescript通过类型注解提供编译时的静态类型检查。typescript可处理已有的Javascript代码,并对其中的typescript代码进行编译。
JavaScript | TypeScript |
---|---|
一种脚本语言,用于创建动态网页 | JavaScript 的超集用于解决大型项目的代码复杂性 |
作为一种解释型语言,只能在运行时发现错误 | 可以在编译期间发现并纠正错误 |
弱类型,没有静态类型选项 | 强类型,支持静态和动态类型 |
可以直接在浏览器中使用 | 最终被编译成 JavaScript 代码,使浏览器可以理解 |
不支持模块,泛型或接口 | 支持模块、泛型和接口 |
不支持编译其他 ES3,ES4,ES5 或 ES6 功能 | 支持 ES3,ES4,ES5 和 ES6 等 |
3、编译及优化TypeScript
- 安装typescript编译器:
npm i typescript -g
- 解决TS和JS冲突问题(生成配置文件):
tsc --init
- 自动编译:
tsc --watch
- 发出错误(有错误不允许编译成js文件):
tsc --noEmitOnError
4、tsconfig.json配置文件
tsc --init
后会生成一个tsconfig.json配置文件
- tsconfig.json文件作用
- 用于标识 TypeScript 项目的根路径;
- 用于配置 TypeScript 编译器;
- 用于指定编译的文件。
- tsconfig.json 重要字段
- files - 设置要编译的文件的名称;
- include - 设置需要进行编译的文件,支持路径模式匹配;
- exclude - 设置无需进行编译的文件,支持路径模式匹配;
- compilerOptions - 设置与编译流程相关的选项。
- compilerOptions 选项
compilerOptions 支持很多选项,常见的有 baseUrl、 target、baseUrl、 moduleResolution 和 lib 等。
compilerOptions 每个选项的详细说明如下:
{
"compilerOptions": {
/* 基本选项 */
"target": "es5", // 指定 ECMAScript 目标版本: 'ES3' (default), 'ES5', 'ES6'/'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'
"module": "commonjs", // 指定使用模块: 'commonjs', 'amd', 'system', 'umd' or 'es2015'
"lib": [], // 指定要包含在编译中的库文件
"allowJs": true, // 允许编译 javascript 文件
"checkJs": true, // 报告 javascript 文件中的错误
"jsx": "preserve", // 指定 jsx 代码的生成: 'preserve', 'react-native', or 'react'
"declaration": true, // 生成相应的 '.d.ts' 文件
"sourceMap": true, // 生成相应的 '.map' 文件
"outFile": "./", // 将输出文件合并为一个文件
"outDir": "./", // 指定输出目录
"rootDir": "./", // 用来控制输出目录结构 --outDir.
"removeComments": true, // 删除编译后的所有的注释
"noEmit": true, // 不生成输出文件
"importHelpers": true, // 从 tslib 导入辅助工具函数
"isolatedModules": true, // 将每个文件做为单独的模块 (与 'ts.transpileModule' 类似).
/* 严格的类型检查选项 */
"strict": true, // 启用所有严格类型检查选项
"noImplicitAny": true, // 在表达式和声明上有隐含的 any类型时报错
"strictNullChecks": true, // 启用严格的 null 检查
"noImplicitThis": true, // 当 this 表达式值为 any 类型的时候,生成一个错误
"alwaysStrict": true, // 以严格模式检查每个模块,并在每个文件里加入 'use strict'
/* 额外的检查 */
"noUnusedLocals": true, // 有未使用的变量时,抛出错误
"noUnusedParameters": true, // 有未使用的参数时,抛出错误
"noImplicitReturns": true, // 并不是所有函数里的代码都有返回值时,抛出错误
"noFallthroughCasesInSwitch": true, // 报告 switch 语句的 fallthrough 错误。(即,不允许 switch 的 case 语句贯穿)
/* 模块解析选项 */
"moduleResolution": "node", // 选择模块解析策略: 'node' (Node.js) or 'classic' (TypeScript pre-1.6)
"baseUrl": "./", // 用于解析非相对模块名称的基目录
"paths": {
}, // 模块名到基于 baseUrl 的路径映射的列表
"rootDirs": [], // 根文件夹列表,其组合内容表示项目运行时的结构内容
"typeRoots": [], // 包含类型声明的文件列表
"types": [], // 需要包含的类型声明文件名列表
"allowSyntheticDefaultImports": true, // 允许从没有设置默认导出的模块中默认导入。
/* Source Map Options */
"sourceRoot": "./", // 指定调试器应该找到 TypeScript 文件而不是源文件的位置
"mapRoot": "./", // 指定调试器应该找到映射文件而不是生成文件的位置
"inlineSourceMap": true, // 生成单个 soucemaps 文件,而不是将 sourcemaps 生成不同的文件
"inlineSources": true, // 将代码与 sourcemaps 生成到一个文件中,要求同时设置了 --inlineSourceMap 或 --sourceMap 属性
/* 其他选项 */
"experimentalDecorators": true, // 启用装饰器
"emitDecoratorMetadata": true // 为装饰器提供元数据的支持
}
}
2、TypeScript常用类型
1、基元类型 string、number、boolean
let str: string = 'hello world';
let num: number = 123;
let b: boolean = true;
2、数组
let arr: number[] = [1,2,3];
let arr1: Array<number> = [2,3,4]; // Array<number>泛型语法
3、any
不希望某个特定值导致类型检查错误
在 TypeScript 中,任何类型都可以被归为 any 类型。这让 any 类型成为了类型系统的顶级类型(也被称作全局超级类型)
let notSure: any = 666;
notSure = "Semlinker";
notSure = false;
any 类型本质上是类型系统的一个逃逸舱。作为开发者,这给了我们很大的自由:TypeScript 允许我们对 any 类型的值执行任何操作,而无需事先执行任何形式的检查。
在许多场景下,这太宽松了。使用 any 类型,可以很容易地编写类型正确但在运行时有问题的代码。如果我们使用 any 类型,就无法使用 TypeScript 提供的大量的保护机制。为了解决 any 带来的问题,TypeScript 3.0 引入了 unknown 类型。
4、unknown类型
就像所有类型都可以赋值给 any,所有类型也都可以赋值给 unknown。这使得 unknown 成为 TypeScript 类型系统的另一种顶级类型(另一种是 any)。
unknown 和 any 的主要区别是 unknown 类型会更加严格:在对 unknown 类型的值执行大多数操作之前,我们必须进行某种形式的检查。而在对 any 类型的值执行操作之前,我们不必进行任何检查。
let foo: any = 123;
console.log(foo.msg); // 符合TS的语法
let a_value1: unknown = foo; // OK
let a_value2: any = foo; // OK
let a_value3: string = foo; // OK
let bar: unknown = 222; // OK
console.log(bar.msg); // Error
let k_value1: unknown = bar; // OK
let K_value2: any = bar; // OK
let K_value3: string = bar; // Error
因为bar是一个未知类型(任何类型的数据都可以赋给 unknown 类型),所以不能确定是否有msg属性。不能通过TS语法检测;而 unkown 类型的值也不能将值赋给 any 和 unkown 之外的类型变量
any 和 unknown 都是顶级类型,但是 unknown 更加严格,不像 any 那样不做类型检查,反而 unknown 因为未知性质,不允许访问属性,不允许赋值给其他有明确类型的变量
5、void
某种程度上来说,void 类型像是与 any 类型相反,它表示没有任何类型。当一个函数没有返回值时,你通常会见到其返回值类型是 void。
需要注意的是,声明一个 void 类型的变量没有什么作用,因为它的值只能为 undefined 或 null:
let unusable: void = undefined;
6、null 和 undefined 类型
let u: undefined = undefined;
let n: null = null;
7、nerver类型
在TypeScript中,never类型表示的是那些永不存在的值的类型,例如,never类型是那些总是会抛出异常或根本就不会有返回值的函数表达式或箭头函数表达式的返回值类型。此外,变量也可能是never类型,当它们被永不为真的类型保护约束时。
在定义变量是可以设置变量的类型为never类型:let nevername: never; //定义never类型的变量
never类型是任何类型的子类型,也可以赋值给任何类型:
let bar: string = (()=>{
throw new Error('ts never');
})();
然而,没有类型是never的子类型或可以赋值给never类型(除了never本身之外)。即使any也不可以赋值给never:
let baz: never = 123; //赋值失败,number类型不能赋值给never
使用never的目的:避免出现新增了联合类型没有对应的实现,目的就是写出类型绝对安全的代码。
8、函数
需要确认参数的类型和返回值的类型,例如如下参数类型为string,void表示没有返回值