TS入门学习笔记

1,219 阅读8分钟

强类型语言与弱类型语言

强类型语言:

 强类型语言不允许改变变量的数据类型,除非进行强制类型转换。

弱类型语言:

定义与强类型语言相反,一个变量可以被赋予不同数据类型的值。

var a = 'a';
var b = 111;
a = b;
console.log(a) // 111

动态类型语言与静态类型语

动态类型语言: 在执行阶段才做类型检查。

例如:js/python等就是属于动态类型语言,对类型检查非常宽松

静态类型语言: 在编译阶段就做类型检查

例如: c++/Java等属于静态类型语言,对类型检查非常严格,bug在编译阶段就会被发现。

基础类型

ES6的类型可以分为Boolean,Number,String,Array,Function,Object,Symbol,undefined,null。

TypeScript的数据类型则在ES6的基础上加上void,any,never,元组,枚举,高级类型。

基础语法:

: type

TypeScript的基本类型语法是在变量之后使用冒号进行类型标识

这种语法也揭示了TypeScript的类型声明实际上是可选的。

1、number类型

let num: number = 123

2、boolean

boolean是最基础的数据类型,在ts中,使用boolean来定义布尔值

let isCheck: boolean = false;

3、string

在ts中,使用string来定义字符串类型

let name: string = 'Mi FE'

4、undefined和null

在TypeScript里,undefined和null两者各自有自己的类型分别叫做undefined和null。

和 void相似,它们的本身的类型用处不是很大:

undefined类型的数据只能被赋值为undefined

在typescript中,已声明未经过初始化的值要直接访问的话,类型需要定义为undefind

null类型只能被 被赋值为null

null为一个空指针对象,undefined是一个未初始化的变量。所以,可以把undefined看成一个空变量,把null看成一个空对象。

特别注意:默认情况,undefined和null类型,是所有其他类型的子类型,所以也就是说,它两可以给所有其他类型赋值。

let _undefined: undefined = undefined;

let _null: null = null;

5、array

在ts中,定义数组方式有两种: 可以在元素类型后面接上[],表示由此元素组成的一个数组:

let arr1: number[] = [1, 2, 3]

使用数组泛型,Array<元素类型> :

let arr2: Array<number> = [1, 2, 3]

构造函数

let arr3: string[] = new Array(‘a’, ‘b’)

联合类型:这里的联合类型是指,数组中的元素类型可以是,联合类型包含的类型。

let arr4: Array<number | string> = [0, ‘1’]

6、元组

元组类型允许表示一个已知元素数量和类型的数组,各元素的类型不必相同。 比如,你可以定义一对值分别为number和string类型的元组。

let hello: [number, string] = [0, 'hello']

元组和数组看起来有点类似,但是区别在于元组的长度是有限的,而且分别为每一个元素定义了类型

7、枚举

enum类型是对JavaScript标准数据类型的一个补充。 像C#等其它语言一样,使用枚举类型可以为一组数值赋予友好的名字。

// nan = 1 数字枚举下标是从0开始的,可以自行设置枚举成员的初始值,他们会依次增加。
enum NUM {
	F,
	S,
	T
}
	
console.log(NUM.F) //0
console.log(NUM.S) //1
console.log(NUM.T)// 2

8、void

表示没有任何返回值,一般用于定义方法是方法没有返回值

function f1() : void {
	console.log(‘函数无返回值,为void类型’)
}

9、any

其他类型都是any类型的子类型,any类型的值可以被赋值为任何类型的值

let something: any = 42;
something.mayExist() //没问题,因为可能在运行时存在该方法
something.toFixed() //没问题,方法确实存在,编译器不会去检查

10、never

如果一个函数永远没有返回值时,我们可以声明其为void类型:

function fn(): never {
    throw new Error('never');
}

11、日期类型

let da: Date = new Date()

12、正则表达式类型

//构造函数神声明法
let rg1 : RegExp = new RegExp(‘hyx’, gi)
		
//字面量的声明法
let rg2: RegExp = /hyx/gi

函数

函数定义:定义函数有函数声明和函数表达式两种形式,定义函数的参数和返回值可以指定其类型;当调用函数时,传入参数类型必须与定义函数参数类型保持一致。

1、函数声明定义:

//输入类型	     输出类型
function fn(age:number) : string{
	return ‘今年 ${age} 岁’;
}

2、函数表达式定义

// a
let f1 = (age:number):string => {
	  return ‘今年 ${age } 岁’
	}
	
let age : number = 22;
let res : string = f(age);
console.log(res);//今年22岁

⚠️注意:表达式定义完以后,必须调用函数

函数表达式还存在另一种写法: 函数表达式:指定变量fn的类型。

1、函数没有返回值可以使用void类型指定返回值

// b
function f3(): viod {
  console.log(‘没有返回值’);
}
f3()

2、可选参数的函数

注意⚠️:可选参数一定要放在参数的最后面。

// c
function f4(age: number, cm?:number) :string {
	//cm	为可选参数,可传可不传
}

3、剩余参数的函数

当有很多参数的时候,或者函数的个数不确定,可以使用三点运算符。

// d
function  fn (…rest: number[] : number[] ) {
	return […rest]
}
console.log(fn(1, 3, 5, 7, 9))
	
function fn2(a:number, b:number, …rest: number[]): number[] {
	return [a, b, …rest ];
}
	
console.log(fn2(10, 22, 1, 3, 5, 7, 9))

4、函数的重载

先声明所有方法重载的定义,不包含方法方法的实现,再声明一个参数为any类型的重载方法,实现any类型1的方法并通过参数类型(和返回类型)不同,来实现重载。

Typescript中的重载:通过为同一函数提供多个函数定义来实现多种功能的目的,Typescript会优先从最前面的函数定义开始匹配,所以多个函数如果有包含关系,需要优先把精确的定义写在前面。

function f1(x: number, y: number) :number;
function f1(x: string, y: string): string;

//上面定义函数的格式,下面定义函数的具体实现
function f1 (x:any, y:any): any {
  return x+y;
}

f1(1, 2);
f1(‘a’, ‘b’);

1、Ts多态

在父亲类定义方法但是不去实现,让继承他的子类来实现该方法,这样就使得每一个子类都会改方法有了不同的表现形式。

2、类和接口

类可以实现接口,通过接口,你可以强制地指明类遵守的某个契约。你可以在接口中声明一个方法,然后要求类去具体实现它。
接口不可以被实例化,实现接口必须重写接口中的抽象方法。

3、类和接口的区别

a、类可以实现多个接口,但只能扩展自一个抽象类。

b、抽象类中可以包含具体实现,但是接口不可以。

c、抽象类在运行中是可见的,可以通过instanceof判断。接口则直线编译时起作用。

d、接口只能描述类的公共部分,不会检查私有成员,而抽象没有这样的限制。

4、抽象类和抽象方法

a、用abstract关键字定义抽象类和抽象方法,抽象类中的抽象方法不包括具体实现并且必须在派生类中实现。

b、抽象类:它是提供其他类继承的基础类,不能直接被实例化,子类继承可以被实例化。
   abstract修饰的方法(抽象方法),只能放在抽象类中
   
c、抽象类和抽象方法用来定义标准版(比如定义标准为:抽象类中有抽象方法,要求他的子类必须也要有这个方法)

5、接口:

a、接口定义:接口是对传入参数进行约束,或者对类里面的属性和方法进行声明和约束,实现这个接口的类必须实现该接口里面的属性和方法;typeScript的接口用interface关键字来定义。

b、接口作用:接口定义了某一批类所需要遵守的规范,接口不关心这些类的内部状态数据。也不关心这些类里方法的实现细节,它只规定这批类里面必须提供某些方法1,提供这些方法的的类就可以满足实际需要。ytpescript接口类似于java,同是还增加了更灵活的接口类型,包括属性,函数,可索引和类等。

c、属性接口:对传入对象的约束,也就是Json数据。

d、函数类型的接口:对方法传入的参数和返回值进行约束。

e、可索引的接口:对索引传入的参数的约束。

f、类和类型接口:对类的约束。对类的属性和方法进行约束,类实现接口要用implements,子类必须实现接口里面声明的属性和方法。

g、接口继承:如果父接口中有定义的但没有实现的方法,实现子接口时,必须也要实现继承于父类接口中的方法。

泛型

定义:不预先确定的数据类型,具体的类型需要在使用的时候才能确定

例子: 声明一个打印函数,实现把传入的字符串打印出来:

function log(value: string): string {
    console.log(value)
    return value
}

加一个需求,要实现能把字符串数组也打印出来:

function log(value: string): string
function log(value: string[]): string[]
function log(value: any): {
  console.log(value)
  return value
}

如上所示,可以用之前的函数重载来实现。

再加一个需求,要实现能把任何类型的参数打印出来。泛型就派上用场了:

function log<T>(value: T): T {
  console.log(value);
  return value;
}