强类型语言与弱类型语言
强类型语言:
强类型语言不允许改变变量的数据类型,除非进行强制类型转换。
弱类型语言:
定义与强类型语言相反,一个变量可以被赋予不同数据类型的值。
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;
}