TypeScript 极速梳理
JavaScript
是非常灵活的一门编程语言,但是这种灵活是把双刃剑,一方面使得JavaScript蓬勃发展,无所不能;另一方面也使它的代码质量参差不齐,维护成本高,运行时错误多。
TypeScript
是具有类型的JavaScript,在很大程度上弥补了它的缺点。
类型声明
给变量声明类型:
1 | let a:string // 变量a只能存储字符串 |
给参数声明类型
1 | // 给x和y传递参数时必须传递数字类型,返回值也必须是数字 |
类型推断
在没有声明类型的情况下,ts会自行推断出类型
1 | let d = -99 // 此时会自动推断变量d的类型为数字 |
类型总览
JavaScript
中的数据类型:
备注: 其中
object
包括:Array
、Function
、Date
…..
TypeScript
中的数据类型:
注意:
JavaScript
中的三个构造函数:Number
、String
、Boolean
,他们只用于包装对象,正常开发时,很少去使用他们,在TypeScript
中也是同理
总览:
类型 | 描述 | 举例 |
---|---|---|
number |
任意数字 | 1 ,-1 ,1.5 |
string |
任意字符串 | 'nihao' ,'你好' ,'hello' |
boolean |
布尔值 | true &false |
字面量 |
值只能是字面量值 | 值本身 |
any |
任意类型 | 1 ,'hello' ,true …… |
unknown |
类型安全的any |
1 ,'hello' ,true …… |
never |
不能是任何值 | 无值 |
void |
空 或 undefined |
空 或 undefined |
object |
任意JS 对象 |
{name: '张三'} |
tuple |
元素,TS 新增类型,固定长度数组 |
[3, 4] |
enum |
枚举,TS 新增类型 |
enum{A, B} |
常用类型
字面量
1 | let a:'你好' // a的值只能是字符串'你好' |
any
any
的含义是:任何类型。 一旦将变量类型限制为any
,那就意味着放弃了对该变量的类型检查。
1 | // 明确表示a的类型是any —— 显式的any |
注意: any 类型的变量,可以赋值给任意类型的变量 :
1
2
3 let a
let x:string
x = a // ⽆警告
unknown
unknown
的含义是:未知类型
unknown
可以理解为一个类型安全的any
unknown
适用于:开始不知道数据的具体类型,后期才能确定数据的类型
1 | // 设置a的类型为unknown |
如果想把a赋值给x, 可以用以下三种写法:
1 | // 设置a的类型为unknown |
any
后点任何的东西都不会报错,unknown
则相反
1 | let str1:string = 'hello' |
never
never
的含义是:任何值都不是,简言之就是不能有值,undefined
、null
、''
、0
都不行!
几乎不用
never
去限制变量,因为没有意义,例如:1
2
3
4
5
6
7
8// 指定a的类型为never,那就意味着a以后不能存任何的数据
let a:never
// 以下对a的赋值都会有警告
a = 1
a = true
a = undefined
a = nullnever
一般是TypeScript
主动推断出来的,例如:1
2
3
4
5
6
7
8
9
10// 指定a的类型为string
let a:string
// 给a设置一个值
a = 'hello'
if(typeof a === 'string'){
a.toUpperCase()
} else{
console.log(a) // TypeScript会推断出此处的a是never,因为没有任何一个值符合此处的逻辑
}never
也可以用于限制函数的返回值1
2
3
4// 限制demo函数不需要有任何返回值,任何值都不行,想undefined和null都不行
function demo():never{
throw new Error('程序异常退出')
}
void
void
的含义是:空
或者undefined
,严格模式下不能加null
赋值给void
类型。
1 | let a:void = undefined |
void
常用于限制函数返回值
1 | // 无警告 |
object
关于Object
与object
,直接说结论:在类型限制时,Object
几乎不用,因为范围太大没有意义。
object
的含义:任何【⾮原始值类型】,包括:对象、函数、数组等,限制的范围⽐较宽泛,⽤的少1
2
3
4
5
6
7
8
9
10
11
12
13
14let a:object // a的值可以是任何【⾮原始值类型】,包括:对象、函数、数组等
// 以下代码,是将【⾮原始类型】赋给a,所以均⽆警告
a = {}
a = {name: '张三'}
a = [1, 3, 5, 7, 9]
a = function(){}
// 以下代码,是将【原始类型】赋给a,有警告
a = null // 警告:不能将类型“null”分配给类型“object”
a = 1 // 警告:不能将类型“number”分配给类型“object”
a = true // 警告:不能将类型“boolean”分配给类型“object”
a = undefined // 警告:不能将类型“undefined”分配给类型“object”
a = '你好' // 警告:不能将类型“string”分配给类型“object”Object
的含义:Object
的实例对象,限制范围太大了,几乎不用1
2
3
4
5
6
7
8
9
10
11
12
13
14let a:Object //a的值必须是Object的实例对象,
// 以下代码,均⽆警告,因为给a赋的值,都是Object的实例对象
a = {}
a = {name:'张三'}
a = [1,3,5,7,9]
a = function(){}
a = 1 // 1不是Object的实例对象,但其包装对象是Object的实例
a = true // true不是Object的实例对象,但其包装对象是Object的实例
a = '你好' // “你好”不是Object的实例对象,但其包装对象是Object的实例
// 以下代码均有警告
a = null // 警告:不能将类型“null”分配给类型“Object”
a = undefined // 警告:不能将类型“undefined”分配给类型“Object”实际开发中,限制一般对象,通常使用一下形式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24// 限制person对象的具体内容,使用','分隔,问号代表可选属性
let person:{
name:string,
age?:number,
}
// 限制car对象的具体内容,使用';'分隔,必须有price和color属性,其他属性不去限制,有没有都行
let car:{
price: number;
color: string;
[k:string]:any
}
// 限制student对象的具体内容,使用'回车'分隔。
let student:{
id:string,
grade:number,
}
// 以下代码均无警告
person = {name: '张三', age: 18,}
person = {name: '李四'}
car = {price: 100, color: '红色'}
student = {id: '123', grade: 3}限制函数的参数、返回值,使⽤以下形式
1
2
3
4
5let demo:(a:number, b:number) => number
demo = function(x, y){
return x + y
}限制数组,使用以下形式
1
2
3
4
5let arr1:string[] // 等价于 let arr1:Array<string>
let arr2:number[] //等价于 let arr2:Array<number>
arr1 = ['a', 'b', 'c']
arr2 = [1, 3, 5, 7, 9]
tuple
tuple
就是一个长度固定的数组。
1 | let t:[string, number] |
enum
enum
是枚举
1 |
|
自定义类型
⾃定义类型,可以更灵活的限制类型
1 | // 性别的枚举 |
抽象类
常规类:
1 | class Person { |
继承:
1 | // Person类 |
抽象类:不能去实例化,但可以被别⼈继承,抽象类⾥有抽象⽅法
1 | // Person(抽象类) |
接口
接口梳理:
接口用于限制一个类中包含那些属性和方法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23// Person 接口
interface Person {
// 属性声明
name: string
age: number
// 方法声明
speak():void
}
// Teacher实现Person接口
class Teacher implements Person {
name: string
age: number
// 构造器
constructor(name: string, age: number){
this.name = name
this.age = age
}
// 方法
speak(){
console.log('你好,我是:', this.name)
}
}接口是可以重复声明的:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27// Person接口
interface PersonInter {
// 属性声明
name: sting
age: number
}
// Person接口
interface PersonInter {
// 方法声明
speak():void
}
// Person类继承PersonInter
class Person implements PersonInter {
name: string
age: number
// 构造器
constructor(name: string, age: number){
this.name = name
this.age = age
}
// 方法
speak(){
console.log('你好,我是:', this.name)
}
}“接口”与”自定义类型”的区别:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24// Person接口
interface Person{
// 应该具有的属性
name: string
age: number
// 应该具有的方法
speak():void
}
// Person类型
/*
* type Person = {
* name: string
* age: number
* }
*/
// 接口当自定义类型去使用
let person:Person = {
name: '张三',
age: 18,
speak(){
console.log("你好")
}
}“接口”与”抽象类”的区别
抽象类举例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26// 抽象类 ——— Person
abstract class Person{
// 属性
name: string
age: number
// 构造器
constructor(name:string, age:number){
this.name = name
this.age = age
}
// 抽象方法
abstract speak():void
// 普通方法
walk(){
console.log('我在走')
}
}
// Teacher类继承抽象类Person
class Teacher extends Person {
constructor(name:string, age:number){
super(name, age)
}
speak(){
console.log(`我是${this.name}`)
}
}接口举例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20// 接口 ——— Person, 只能包含抽象方法
interface Person {
// 属性,不写具体值
name: string
age: number
// 方法,不写具体实现
speak():void
}
// 创建Teacher类实现Person接口
class Teacher implements Person {
name: string
age: number
constructor(name:string, age:number){
this.name = name
this.age = age
}
speak(){
console.log('我在走')
}
}
属性修饰符
修饰符 | 含义 | 解释 |
---|---|---|
readonly |
只读属性 | 属性无法更改 |
public |
公开的 | 可以在类、子类和对象中修改 |
protected |
受保护的 | 可以在类、子类中修改 |
private |
私有的 | 可以在类中修改 |
泛型
定义一个函数或类时,有些情况下无法确定其中要使用的具体类型(返回值、参数、属性的类型不能确定),此时就需要泛型了
举例:<T>
就是泛型,(不一定非叫<T>
),设置泛型之后即可在函数中使用T
来表示该类型:
1 | function text<T>(arg: T): T{ |
泛型还可以写多个:
1 | function test<T, K>(a: T, b: K) K{ |
类中同样可以使用泛型
1 | class MyClass<T>{ |
也可以对泛型的范围进行约束:
1 | interface Demo{ |
结语
希望以上笔记能对你有帮助,当然如果你在使用TS时弄不清类型,又不想看到警告,完全可以使用any
声明。这也是为什么TypeScript
又被大家叫做AnyScript
🤪
TypeScript 极速梳理