简介
- 静态类型语言:在编译阶段确定所有变量的类型
- 动态类型语言:在执行阶段确定所有变量的类型
- TypeScript是JavaScript的超集,它对JS进行了扩展,向JS中引入了类型的概念,并添加了许多新的特性。
- TS代码需要通过编译器编译为JS,然后再交由JS解析器执行。
- TS完全兼容JS,换言之,任何的JS代码都可以直接当成JS使用。
- 相较于JS而言,TS拥有了静态类型,更加严格的语法,更强大的功能;TS可以在代码执行前就完成代码的检查,减小了运行时异常的出现的几率;TS代码可以编译为任意版本的JS代码,可有效解决不同JS运行环境的兼容问题;同样的功能,TS的代码量要大于JS,但由于TS的代码结构更加清晰,变量类型更加明确,在后期代码的维护中TS却远远胜于JS。
安装
- 使用npm全局安装typescript
npm i -g typescript
- 创建一个ts文件,使用tsc对ts文件进行编译,执行命令:tsc xxx.ts
配置
-
tsc --init
生成 tsconfig.json 配置文件,tsconfig.json 可以写注释 - tsconfig.json 中的一些配置属性
- include 用来指定哪些ts文件需要被编译,路径:** 表示任意目录,* 表示任意文件
- exclude 不需要被编译的文件目录,默认值:["node_modules", "bower_components", "jspm_packages"]
- compilerOptions 编译器的选项
- noImplicitThis 不允许不明确类型的this
function fn2(this: Window){
alert(this);
}
- strictNullChecks 严格的检查空值
let box1 = document.getElementById('box1');
// if(box1 !== null){
// box1.addEventListener('click', function (){
// alert('hello');
// });
// }
// 添加问号 box1存在的情况下才可以调用addEventListener方法
box1?.addEventListener('click', function (){
alert('hello');
});
{
/*
tsconfig.json是ts编译器的配置文件,ts编译器可以根据它的信息来对代码进行编译
"include" 用来指定哪些ts文件需要被编译
路径:** 表示任意目录
* 表示任意文件
"exclude" 不需要被编译的文件目录
默认值:["node_modules", "bower_components", "jspm_packages"]
*/
"include": [
"./src/**/*"
],
"exclude": [
"./src/hello/**/*"
]
// compilerOptions 编译器的选项
"compilerOptions": {
// target 用来指定ts被编译为的ES的版本
"target": "es2015",
// module 指定要使用的模块化的规范
"module": "es2015",
// lib用来指定项目中要使用的库
"lib": ["es6", "dom"]
// outDir 用来指定编译后文件所在的目录
"outDir": "./dist",
// 将代码合并为一个文件
// 设置outFile后,所有的全局作用域中的代码会合并到同一个文件中
//"outFile": "./dist/app.js"
// 是否对js文件进行编译,默认是false
// "allowJs": true,
// 是否检查js代码是否符合语法规范,默认是false
// "checkJs": true,
// 是否移除注释
"removeComments": true,
// 不生成编译后的文件
"noEmit": false,
// 当有错误时不生成编译后的文件
"noEmitOnError": true,
// 所有严格检查的总开关
"strict": true,
// 用来设置编译后的文件是否使用严格模式,默认false
"alwaysStrict": true,
// 不允许隐式的any类型
"noImplicitAny": true,
// 不允许不明确类型的this
"noImplicitThis": true,
// 严格的检查空值
"strictNullChecks": true
}
}
类型
基本类型
- boolean
- number
- string
- array
- 元组类型(tuple)
- 枚举类型(enum)
- 任意类型(any)
- null
- undefined
- object
- void
- never
高级类型
- union 组合类型
- Nullable 可空类型
- Literal 预定义类型
自动类型判断
- TS拥有自动的类型判断机制
- 当对变量的声明和赋值是同时进行的,TS编译器会自动判断变量的类型
- 所以如果变量的声明和赋值是同时进行的,可以省略掉类型声明
// 声明完变量直接进行赋值
// let c: boolean = false;
// 如果变量的声明和赋值是同时进行的,TS可以自动对变量进行类型检测
// c只能是布尔类型的值
let c = false;
c = true;
类型声明
TS中的类型判断一般用于函数的参数和函数的返回值的情况较多,因为JS中的函数是不考虑参数的类型和个数的
// JS中的函数是不考虑参数的类型和个数的
// function sum(a, b){
// return a + b;
// }
// console.log(sum(123, 456)); // 579
// console.log(sum(123, "456")); // "123456"
function sum(a: number, b: number): number{
return a + b;
}
let result = sum(123, 456);
类型断言(类型适配)
类型断言,可以用来告诉编辑器变量的实际类型,使用类型断言一定要对当前对象的类型有百分之百的信心,否则会出现严重的错误
/*
* 语法:
* 变量 as 类型
* <类型>变量
* */
s = e as string;
s = e;
let message: any
message = "abc"
message.endsWith("c") //调用endWith方法的时候,编辑器并不会出现提示,因为此时message还是any类型,即使已经用一个string 类型赋值了 这个时候可以使用类型断言
// 法一
let ddd = (message).endsWith("c")
// 法二
let ddd2 = (message as string).endsWith("c")
元组类型(tuple) 固定长度的数组
// 该数组 第一个元素是number类型 第二个元素是string类型 并且数组长度只能是2位
let arr: [number, string] = [123, "this is ts"]
// arr.push(3) 这边一定要注意元组是固定类型的,是不能够push的,但是这句话编译会通过 平时一定要注意
在声明元组的时候一定要指定类型,如果没有指定类型,其实本质上是一个联合类型数组
let p2 = [1, 'haha'] // p2是一个数组 既不固定长度,也不固定数组
p2[0] = "ddd" // 可以让第一位为字符串,也可以让第二位为数字
p2[1] = 1
p2[2] = 5 // 也可以添加第3位
枚举类型
适合结果在多个值之间进行选择
enum Gender{
Male,
Female
}
let i: {name: string, gender: Gender};
i = {
name: '孙悟空',
gender: Gender.Male // 'male'
}
联合类型(限制变量在某几个值之间)
let union: string | number
union = 2
union = "haha"
let union2: number | string | boolean | string[]
function merge(n1: number | string, n2: number | string) {
// 进行简单的类型适配
if (typeof n1 === "string" || typeof n2 === "string") {
return n1.toString() + n2.toString() // 这边有点疑问
} else {
return n1 + n2
}
}
let mergeNumber = merge(2, 5)
let mergeString = merge("hello", 1)
console.log(mergeString)
// 明确数据的联合类型 union3 只能是0 1 2 也是字面量类型
let union3: 0 | 1 | 2
字面量类型
// 也可以直接使用字面量进行类型声明
// a只能被赋值为10 不能被赋值为其他值 类似常量 很少使用
let a: 10;
a = 10;
// 字面量形式一般用于或的形式较多
// 可以使用 | 来连接多个类型(联合类型)
let b: "male" | "female";
b = "male";
b = "female";
any 类型
// any 表示的是任意类型,一个变量设置类型为any后相当于对该变量关闭了TS的类型检测
// 使用TS时,不建议使用any类型
// let d: any; 显示any
// 声明变量如果不指定类型,则TS解析器会自动判断变量的类型为any (隐式的any)
let d;
d = 10;
d = 'hello';
d = true;
unknown 类型
// unknown 表示未知类型的值
let e: unknown;
e = 10;
e = "hello";
e = true;
unknown和any的区别在于:any类型的变量可以赋值给任意变量,unknown类型的变量不能直接赋值给其他变量
let s:string;
// d的类型是any,它可以赋值给任意变量
s = d;
e = 'hello';
s = e; // 这句话会报错 即使 e 是字符串 因为 e 原本是 unknown 类型
// unknown 实际上就是一个类型安全的any
// unknown类型的变量,不能直接赋值给其他变量,即使赋值的时候两个变量是同一种类型,赋值之前需要进行类型判断
if(typeof e === "string"){
s = e;
}
void 类型
// void 用来表示空,以函数为例,就表示没有返回值的函数
function fn(): void{
console.log('hahah')
}
never 类型
never 表示永远不会返回结果,连空都没有,一般用于处理报错,函数只要报错,立即执行结束
function fn(): never {
throw new Error("报错了!");
}
object 类型
// object表示一个JS对象 因为JS中一切皆对象,所以单纯这样写,没有任何意义
let a: object;
a = {};
a = function () {
};
一般开发中更多的是对对象的属性进行限制,而不是限制它是不是一个对象
// {} 用来指定对象中可以包含哪些属性,属性的个数要严格相等
// 语法:{属性名:属性值,属性名:属性值}
// 在属性名后边加上?,表示属性是可选的
let b: {name: string, age?: number};
b = {name: '孙悟空', age: 18};
假设要求 c 这个对象有一个name属性,其他属性不做要求,可有可无
// [propName: string]: any 表示任意类型的属性
// propName 是随便起的名字,表示属性名,js中的属性名是字符串类型
let c: {name: string, [propName: string]: any};
c = {name: '猪八戒', age: 18, gender: '男'};
函数结构声明
/*
* 设置函数结构的类型声明:
* 语法:(形参:类型, 形参:类型 ...) => 返回值
* */
// d是一个函数,函数参数是number类型,返回值也是number
let d: (a: number ,b: number) => number;
// d = function (n1: string, n2: string): number{
// return 10;
// }
数组类型声明
2 种定义方式
类型[]
Array<类型>
/*
* 数组的类型声明:
* 类型[]
* Array<类型>
* */
// string[] 表示字符串数组
let e: string[];
e = ['a', 'b', 'c'];
// number[] 表示数值数值
let f: number[];
// 和上述表达方式一样,都是表示数值的数组
let g: Array;
g = [1, 2, 3];
// 三种声明数组的方式都可以
let list1: number[] = [1, 2, 3, 4]
let list2: Array = [1, 2, 3, 4]
let list3 = [1, 2, 3, 4]
JS 中声明的数组可以是混合类型 在 TS中同样也可以做到
let list1 = [1, "ddd"]
let list2: any[] = [1, "dd", true]
其他
&
// &表示同时 表示 j 对象 必须要有 name 和 age 属性
let j: { name: string } & { age: number };
// j = {name: '孙悟空', age: 18};
类型的别名
// 类型的别名
type myType = 1 | 2 | 3 | 4 | 5;
let k: myType;
let l: myType;
let m: myType;
k = 2;