1. 各类型定义
1.1 类型定义
let flag:boolean = false // 布尔类型
let num:number = 3 // 数值类型
let str:string = 'abc' // 字符串类型
let u:undefined = undefined
let n:null = null
void类型 // 用于定义无返回的函数
1.2 任意值
如果一个普通类型,在赋值过程中改变类型是不允许的,任意类型any表示允许赋值为任意类型。
let a2:any = 'abc'
a2 = 7 // 允许
// 如果声明时未指定类型,那么会被识别为any类型
let a3;
a3 = 'abc'
a3 = 7
1.3 联合类型
表示取值可以为多种类型的一种
let a:string|number;
a=4
a='abc'
function getLength(str:string|number):number{
return str.length // 报错,为什么?
}
// 当 TypeScript不确定一个联合类型的变量到底是哪个类型的时候
// 只能访问此联合类型的所有类型里共有的属性或方法
function getLength(str:string|number[]):number{
return str.length
}
console.log(getLength([1,2,3])
1.4 数组类型
// 用「类型 + 方括号」来表示数组
let arr:number[] = [1,2,3]
let arr:string[] = ['a','b','c']
// 泛型:是指在定义函数、接口或类的时候,不预先指定具体的类型,
// 而在使用的时候再指定类型的一种特性
let arr:Array<number> = [1,2,3]
let arr:Array<number|string> = ['a',1,2]
1.5 函数类型的定义
- 输入类型
- 输出类型
// 返回number
function sum(x:number,y:number):number{
return x + y
}
// 返回boolean
function f2(n1:number,n2:number):boolean{
if(n1>n2){
return true;
}else {
return false;
}
};
// 无返回值
function f3(n1:number,n2:number):void{
if(n1>n2){
//....
}else {
//...
}
};
// 参数默认值
function sum(x:number=5,y:number):number{
return x + y
}
// 参数默认值编译后如下:
function sum(x, y) {
if (x === void 0) { x = 5; }
return x + y;
}
console.log('sum:', sum(void 0, 2)); // 5 + 2 =7
// 可选参数
function sum(x:number,y?:number):number[] {
return [x,y]
}
let s2 = sum(1) // [1,undefined]
// 函数表达式
let sum = function(x:number,y:bumber):number{
return x + y
}
// 箭头函数
let sum = (x:number,y:number):number => {
return x + y
}
1.6 类型别名
type n = string|number[]
let fn = (s:n):number => {
return s.length
}
2. 类
2.1 构造函数
// 构造函数
function Cat(name.color) {
this.name = name;
this.color = color;
}
// 原型
Cat.prototype.type='动物';
Cat.prototype.eat = function () {
return console.log("吃老鼠");
};
var cat1 = new Cat("大明","黄色");
var cat2 = new Cat("小明","白色");
2.2 定义类
class Cat {
name: string
color: string
constructor(name:string,color:string) {
this.name = name
this.color = color
}
eat (param: string):string {
return '吃老鼠'
}
}
let cat:Cat = new Cat('小花','white')
2.3 类的继承
class Animal {
name:string;
constructor(name:string){
this.name = name
}
eat(){
console.log('吃肉')
return '吃肉'
}
}
// 继承
class Dog extends Animal {
constructor(name:string){
super(name) // 调用父类的constructor(name) //Animal.prototype.constructor.call(this);
}
sayHi(){
return `${this.name}:${this.eat()} ` // 调用父类的eat方法
}
}
let dog:Dog = new Dog('tom')
dog.sayHi()
2.4 修饰符
- 修饰符是用于限定类型以及类型成员声明的一种符号。
- static 使用修饰符static修饰的方法称为静态方法,它们不需要实例化,而是直接通过类来调用:
- public 修饰的属性或方法是公有的,可以在任何地方被访问到,默认所有的属性和方法都是 public 的;
- private 修饰的属性或方法是私有的,不能在声明它的类的外部访问;
- protected 修饰的属性或方法是受保护的,它和 private 类似,区别是它在子类中也是允许被访问的;
// static 使用修饰符static修饰的方法称为静态方法,它们不需要实例化,而是直接通过类来调用:
class Obj1{
name:string;
constructor(name){
this.name = name;
}
static action(state:string):string{
return state;
}
};
let o1 = new Obj1("Tom"); //实例化
o1.action("play"); // 报错
Obj1.action("play"); //不需要实例化,而是直接通过类来调用
// public 修饰的属性或方法是公有的,可以在任何地方被访问到,默认所有的属性和方法都是 public 的;
class Obj2{
public name:string;
public constructor(name){
this.name = name;
}
public action(state:string):string{
return state;
}
};
let o2 = new Obj2("Tom"); //实例化
o2.name;
o2.action('sing');
// private 修饰的属性或方法是私有的,不能在声明它的类的外部访问;
class Obj3{
private name:string;
public constructor(name){
this.name = name;
}
private action(state:string):string{
return state = this.name;
}
};
let o3 = new Obj3("Tom");
o3.name; //不能访问
o3.action('play'); //不能访问
// protected 修饰的属性或方法是受保护的,它和 private 类似,区别是它在子类中也是允许被访问的;
class Obj4{
protected name:string;
public constructor(name){
this.name = name;
}
protected action(state:string):string{
return state = this.name;
}
};
let o4 = new Obj4("Jack");
o4.name; // 提示错误,只能Obj4 和它的子类访问
o4.action("sing"); // 提示错误,只能Obj4 和它的子类访问
2.5 类实现接口
interface IFeatures {
name?:string;
age:number;
height?:number;
weight?:number;
action():string;
}
//类受到接口的约束 类实现接口
class Person implements IFeatures {
name:string;
age:number;
constructor(name,age){
this.name=name;
this.age = age;
}
action(){
return '哭';
}
};
let p1 = new Person('abc',18);
// 有时候不同类之间可以有一些共有的特性,这时候就可以把特性提取成接口(interfaces),
// 然后类用 implements 关键字来实现接口
interface IAlarm{
sing();
}
interface Light {
lightOn();
lightOff():boolean;
}
class Door {
}
// 子类继承父类并实现接口
class SecurityDoor extends Door implements IAlarm{
sing(){console.log('134424')}
}
// 类实现多个接口
class Car implements IAlarm , Light{
sing(){}
lightOn(){}
lightOff(){ return true}
}
2.6 类和接口区别
- 一、表示内容不同
- 抽象类:抽象类表示该类中可能已经有一些方法的具体定义。
- 接口:接口就仅仅只能定义各个方法的界面(方法名,参数列表,返回类型),并不关心具体细节。
- 二、性质不同
- 抽象类:抽象类是对象的抽象。
- 接口:接口是一种行为规范。
3. 接口
3.1 对象的类型-接口
接口是对行为的抽象
接口(Interfaces)可以用于对「对象的形状(Shape)」进行描述
// 接口定义
interface Person {
name:string;
age:number;
sex?:string|number; //可选属性
[propName:string]:any; //任意属性
}
let tom:Person = {
name: 'tom',
age:18,
hobby:'sing'
}
// 上面,我们定义了一个接口 Person,接着定义了一个变量tom,它的类型是 Person。
// 这样,我们就约束了 tom 的形状必须和接口 Person 一致。
- 定义的变量比接口少了一些属性是不允许的
- 可选属性:例如(sex?:string|number;)可选属性的含义是该属性可以不存在。这时仍然不允许添加未定义的属性
- 任意属性 :例如( [propName:string]:any;)一个接口允许有任意的属性,确定属性和可选属性都必须是任意属性的子属性
3.2 接口在函数中运用
interface IMsg{
id:number;
msg:string;
}
function f1(obj:IMsg):number {
return obj.id
}
let obj = {id:1,msg:'hello'};
f1(obj);
// f2 和f3 参数类型有共性和返回值
function f2(a:string,b:string):boolean{
return a==b
};
function f3(s1:string,s2:string):boolean{
if(s1<s2){
return true;
}else {
return false;
}
}
// 于是,可以定义接口
interface IinspectFunc {
(x:string,y:string):boolean
}
// 重新调整一下f2,f3
let f2:IinspectFunc = (a,b) => {
return a == b
}
let f3:IinspectFunc = function(a,b) {
if(a < b){
return true;
}else {
return false;
}
}
3.3 接口使用泛型
interface IinspectFunc{
<T>(x:T,y:T):boolean
}
let f1:IinspectFunc = (a,b) => a === b
f1<number>(1,2) // 调用f1
// 第二种写法:泛型参数提前到接口名上
interface IinspectFunc<T>{
(x:T,y:T):boolean
}
let f1:IinspectFunc<number> = (a,b) => a === b
f1(1,2) // 调用
4. 泛型
泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。
4.1 什么时候需要定义泛型函数
要创建一个可重用的组件,其中的数据类型就必须要兼容很多的类型
// 定义一个只能传入number类型的函数
function f(a:number,b:number):number[]{
return [a,b]
}
f(1,2);
// 定义一个只能传入string类型的函数
function f2(a:string,b:string):string[]{
return [a,b]
}
f2('1','3')
// 泛型函数
function f3<T>(a:T,b:T):T[]{
return [a,b]
}
f3<number>(1,2)
f3<string>('a','b')
4.2 不使用泛型
function f6<T>(n1:T,n2:T):T {
return n1+n2 //错误 并不是所有的类型都有+连接符
};
f6<number>(10,20)
function f8<T>(str:T):number {
return str.length //错误,并不是所有的类型都有.length属性
};
4.3 泛型类型
// 函数声明
function mySum<T>(a:T,b:T):T[]{
return [a,b]
}
// 函数表达式
let mySum = function<T>(a:T,b:T):T[]{
return [a,b]
}
// ES6 箭头函数
let mySum = <T>(a:T,b:T):T[] => [a,b]
4.4 泛型约束
interface IlengthN{
length:number
}
let fn = <T extends IlengthN>(n:T):number => n.length
fn<string>('abcd')
4.5 泛型接口
//定义一个函数,传入长度和具体的值,返回数组(数组的长度传入的长度,数组的值传入的值)
function createArray<T>(length:number,value:T):Array<T> {
let arr = [];
for(let i=0;i<length;i++){
arr[i] = value;
};
return arr;
};
createArray<string>(3,'x'); //['x','x','x'];
//扩展一
//定义接口
interface ICreateArrayFun {
<T>(length:number,value:T):Array<T>
};
let createArray2:ICreateArrayFun = function<T>(len,v){
let arr:T[] = [];
for(let i=0;i<len;i++){
arr[i] = v;
};
return arr;
};
createArray2<string>(3,'x'); //['x','x','x'];
//扩展二 value参数类型中必须包括length属性
interface IlengthN3 {
length:number;
};
interface ICreateArrayFun3<T extends IlengthN3> { //泛型约束
(length:number,value:T):Array<T>
};
// 写法2
// interface ICreateArrayFun3 {
// <T extends IlengthN3>(length:number,value:T):Array<T>
// };
let createArray3:ICreateArrayFun3<number[]> = function(len,v){
let arr = [];
for(let i=0;i<len;i++){
arr[i] = v;
};
return arr;
};
createArray3(3,[123]); //['x','x','x'];
4.6 泛型在类中运用
class Obj<T>{
state:T;
constructor(state:T){
this.state = state;
}
action(s:T):T{
return s;
}
};
let o = new Obj<string>('Tom');
//多个类型参数
function fun<N,S>(sum:[N,S]):[S ,N] {
return [sum[1],sum[0]]
};
fun<number,string>([1,'a'])