本文是查阅很多官方文档和优秀文章,将学习的过程总结一下
TS 与 JS 的区别
TypeScript 是一种由微软开发的自由和开源的编程语言。它是 JavaScript 的一个超集,而且本质上向这个语言添加了可选的静态类型和基于类的面向对象编程。 -- 官方文档
Ts包含Js,在Js基础上增加了一些功能,修复了Js存在的问题,在项目中ts更加强大
| Ts | JS |
|---|---|
| JavaScript 的超集,用于解决大型项目的代码复杂性 | 一种脚本语言,用于创建动态网页 |
| 可以在编译期间发现并纠正错误 | 作为一种解释型语言,只能在运行时发现错误 |
| 强类型,支持静态和动态类型 | 动态弱类型语言 |
| 不允许改变变量的数据类型 | 变量可以被赋予不同类型的值 |
| 支持模块、泛型和接口 | 不支持模块,泛型或接口 |
注意:Ts 不能直接被浏览器执行,需要被编译成 JS 才能被浏览器执行
如果不清楚强类型、弱类型的同学,可以先点击查看这篇文章,能更好理解后面学习的内容
创建一个项目来学习太麻烦了,可以直接用线上的ts 演练场来进行学习。
Ts基础类型
Ts的基础类型与Js基础类型差不多,有区别的地方,就是在定义变量的时候,要指定变量类型,并且一旦为变### boolean量指定了类型,就不能再次改变为不同的类型
boolean类型
let isStatus: boolean = true
赋值类型与定义类型的不一致,会报错,例如:
后面的基本类型,同理:
number 类型
let count: number = 100
string 类型
let name: string = 'userName'
undefined 类型
let notHave: undefined = undefined
null 类型
let notHave: null = null
默认情况下 null 和 undefined 是所有类型的子类型。 就是说你可以把 null 和 undefined 赋值给 其他 类型的变量。
注意:如果变量指定了类型,就不能将 null 和 undefined 赋值给改变量了,undefined 只能赋值给 void 和自己,null 只能赋值给自己,不然会报错。
执行以下代码:
let age = null
let name:string = null
let box:void = null
let age1 = undefined
let name1:string = undefined
let box1:void = undefined
结果:
any 类型
使用any类型,Ts就失去了意义。TS 定义变量时用 any 类型,就和写 Js 代码一样了
Ts的有一个非常强大的优点,在编写代码时,要进行检查,来降低代码出bug的概率。
any类型的值执行任何操作,而无需事先执行任何形式的检查。
在 TypeScript 中,任何类型都可以被归为 any 类型。这让 any 类型成为了类型系统的顶级类型(也被称作全局超级类型)。
// 和写 js 代码一样
let age:any = 123
age = '年龄'
age = true
// 可以随便调用属性和方法
let value: any;
value.foo.bar; // OK
value.trim(); // OK
value(); // OK
new value(); // OK
value[0][1]; // OK
缺点:
使用 any 类型,可以很容易地编写类型正确但在运行时有问题的代码,就无法使用 TypeScript 提供的大量的保护机制。
解决方法:为了解决这个问题,TypeScript 3.0 引入了 unknown 类型。
unknown 类型
unknown 类型代表任何类型,它的定义和 any 定义很像,但是它是一个安全类型,使用 unknown 做任何事情都是不合法的。
举个例子:
// value 变量为 unknown 类型
let value:unknown = 12
// 定义一些变量
let num:number
let boo:boolean
let value1:unknown
let value2:any
num = value / 2 // 'value' is of type 'unknown'
boo = value // Type 'unknown' is not assignable to type 'boolean'.
value1 = value // OK
value2 = value // OK
结果:
结论:
1、
unknown类型只能被赋值给any类型和unknown类型本身2、将
any类型改变为unknown类型,允许所有更改的默认设置,更改为禁止任何更改。
实例:
param 定义为 unknown 类型 ,TS 编译器能拦住潜在风险
function divide(param: unknown) {
return param / 2;
}
因为不知道 param 的类型,使用运算符 /,导致报错
解决方法:类型断言
// 对 param 断言,可以理解为这里强制类型转换
function divide(param: unknown) {
return param as number / 2;
}
void 类型
void类型与 any 类型相反,它表示没有任何类型。
function web() {
console.log('hello')
}
web()
结果:
声明一个 void 类型的变量没有什么作用,因为它的值只能为 undefined
never 类型
never类型表示的是那些永不存在的值的类型。
目的就是写出类型绝对安全的代码,非常严谨
有些情况下值会永不存在有些情况下值会永不存在:
- 函数中抛出异常,中断程序的执行
- 死循环
// 异常
function fn(msg: string): never {
throw new Error(msg)
}
// 死循环 千万别这么写,会内存溢出
function fn(): never {
while (true) {}
}
例如:
type Foo = string | number;
function controlFlowAnalysisWithNever(foo: Foo) {
if (typeof foo === "string") {
// 这里 foo 被收窄为 string 类型
} else if (typeof foo === "number") {
// 这里 foo 被收窄为 number 类型
} else {
// foo 在这里是 never
const check: never = foo;
}
}
如果将Foo类型修改成 type Foo = string | number | boolean; ,这时候 else 分支的 foo 类型会被收窄为 boolean 类型,导致无法赋值给 never 类型,这时就会产生一个编译错误。
never 类型是任何类型的子类型,也可以赋值给任何类型。但是没有类型是 never 的子类型,没有类型可以赋值给 never 类型(除了 never 本身之外)。
let test1: never;
test1 = 'lin' // 报错,Type 'string' is not assignable to type 'never'
let test2: any;
test1 = test2 // 报错,Type 'any' is not assignable to type 'never'
结果;
array 数组类型
let list1: number[] = [1, 2, 3];
list1.push(4) // 可以调用数组上的方法
let list2: Array<number> = [1, 2, 3]; // Array<number>泛型语法
如果定义数组为 number 类型,里面的每一个数据也要为 number 类型,否则要报错
问题: 想要数组中的元素,是不同类型的数据,该怎么办呢?
解决方法: 用元组
元组类型(tuple)
元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同。
let tuple: [number, string] = [18, 'lin']
如果对应位置的元素类型和定义的类型不一致,就会报错;如果元素个数和定义的类型个数不一致,也会报错
向元组 push 定义类型的数据时,不会报错;向元组 push 没有定义的数据时,会报做。
Ts 断言
类型断言好比其他语言里的类型转换,但是不进行特殊的数据检查和解构。
只在编译阶段起作用,运行时不起作用 ``
// 方法一、 “尖括号” 语法
let someValue: any = "this is a string";
let strLength: number = (<string>someValue).length;
// as 语法
let someValue: any = "this is a string";
let strLength: number = (someValue as string).length;
Ts 基础知识点远不止这些,后面还有很多,基础学完学进阶知识
学不完,跟本学不完