基础数据类型
number string bolean 字面量 值本身,例'man','woman' any 任意类型 unknown 实际上就是一个类型安全的any void 没有值或undefined never 表示永远不会返回结果 object array
// 基础类型(ts中变量一开始是什么类型,后期赋值的时候,只能用这个类型的数据,是不允许用其他数据类型赋值给当前的这个变量) (() => { //布尔类型 // 基本语法 // let 变量名:数据类型 = 值 let flag: boolean = true console.log(flag) // 数字类型 let a1: number = 10 //十进制 // 还有2进制 8进制 16进制 // 字符串类型 let str: string = '小明' let und: undefined = undefined; let nul: null = null console.log("undefined和null都可以作为其他类型的子类型,把undefined和null赋值给其他变量") // 数组类型(数组定义后,里面的数据类型必须和定义数组的时候是一致的,否则报错) // 数组定义方式1 let arr1: number[] = [10, 20, 30, 40, 50] // 数组定义方式2 let arr2: Array<number> = [100, 200, 300] // 元组类型(在定义数组时,类型和数据的类型一开始就限制了) let arr3: [string, number, Boolean] = ['小明', 100, true] // 枚举类型,枚举里面的每个数据值都可以叫元素,每个元素都有自己的编号,编号是从0开始的,依次的递增1 enum Color { red = 3, green, blue } // 定义一个Color的枚举类型的白能量来接收枚举的值 let color: Color = Color.red console.log(color) console.log(Color.red, Color.green, Color.blue) console.log(Color[3]) // 枚举中的元素可以是中文的数据值,但是不推荐 // any类型 let str9: any = 100 str9 = "我是一个字符串" // 当一个数组要存储多个数据,个数不确定,类型不确定,此时也可以使用any类型来定义数组 let arr: any[] = [100, '字符串', true] // 缺点是不会有精确的报错信息 // void类型,在函数声明的时候,小括号的后面使用:void,代表的是该函数没有任何的返回值 function showMsg(): void { console.log('打印一下') return null } console.log(showMsg()) // 定义一个void类型的变量,可以接收一个undefined的值,但是意义不是很大 let vd: void = undefined console.log(vd) // object 类型 // 定义一个函数,参数是object类型,返回值也是object类型 function getObj(obj: object): object { console.log(obj) return { name: '卡卡西', age: 27 } } console.log(getObj(String)) // console.log(getObj('123')) 错误的 // 联合类型(Union Types)表示取值可以为多种类型中的一种 // 需求1:定义一个函数得到一个数字或字符串值的字符串形式值 // function getString(str: number | string): string { // return str.toString() // } // console.log(getString('123')) // 需求2:定义一个函数得到一个数字或字符串值的长度 // 类型断言:告诉编辑器,我知道我自己是什么类型,也知道自己在干什么 // 类型断言的语法方式1:(<类型>)变量名 // 类型断言的语法方式2: as function getString(str: number | string): number { // return str.toString().length // 如果str自身就是string类型,那么是没有必要调用toString()方法的 if ((<string>str).length) { // str.length存在吗?如果存在也就说明str是string类型的 return (<string>str).length } else { // 此时说明str是number类型 return str.toString().length } } console.log(getString(12345)) console.log(getString('012345')) // 类型推断:没有明确的指定类型的时候推测出一个类型 // let txt = 100 // txt ="字符串" // console.log(txt) let txt2; //any 类型 txt2 = 100 txt2 = '这是一个字符串' console.log(txt2) })()
接口
// 接口:是一种类型,是一种规范,是一种规则,是一个能力,是一种约束 // 同时接口也可以当成类型声明去使用 // 接口可以重复声明,会合并,不能声明重复的属性 // 接口中所有的属性都不能有实际的值,只定义对象的结构 (() => { // 需求:创建人的对象,需要对人的属性进行一定的约束 // id是number类型,必须有,只读的 // name是string类型,必须有 // age是number类型,必须有 // sex是string类型,可以没有 // 定义一个接口,该接口作为person对象的类型使用,限定过着是约束该对象中的属性数据 interface Iperson { //readonly,让id只能读,不能改 readonly id: number name: string age: number sex?: string // ? 实现sex可有可无 } // 定义一个对象,该对象的类型就是我定义的接口IPerson const person: Iperson = { id: 1, name: '小明', age: 18, sex: '女' } console.log(person) // id属性,现在是可读可写的 // person.id = 100 console.log(person) })()
函数类型
类
// 类:可以理解为模板,通过模板可以实例化对象 // 面向对象的编程思想 (() => { // ts中类的定义及使用 class Person { // 定义属性 name: string age: number gender: string // 定义构造函数:为了将来实例化对象的时候,可以直接对属性的值进行初始化 constructor(name: string, age: number, gender: string ) { // 更新对象的中属性数据 this.name = name this.age = age this.gender = gender } // 简写 (k可以省去定义属性的步骤) //constructor(public name: string ,public age: number ,public gender: string) { // 更新对象的中属性数据 //this.name = name //this.age = age //this.gender = gender //} // 定义实列方法 sayHi(str: string) { console.log(`大家好,我是${this.name},今年已经${this.age}岁了,是个${this.gender}孩子`, str) } } // ts中使用类,实例化对象,可以直接进行初始化操作 const person = new Person('佐助', 18, '男') person.sayHi('你叫什么名字呀') })()
修饰符(5个)
// 修饰符(类中的成员的修饰符):主要是描述类中的成员(属性,构造方法,方法)的可访问性 // public修饰符 --- 公共的 可以在任意位置修改,访问 (默认) // private修饰符 ----私有的,只能在类的内部修改 // protected修饰符 ----受保护的,只能在当前类和当前类的子类中修改 // readonly只读 // static 静态方法 (() => { // 定义一个类 class Person { // 属性public 修饰了属性成员 // public name : string // 属性 private 修饰了属性成员 private name: string // 属性protected 修饰了属性成员 // protected name: string // 构造函数 public constructor(name: string) { // 更新属性 this.name = name } // 方法 public eat() { console.log('嗯,这个骨头真好吃', this.name) } } // 定义一个子类 class Student extends Person { // 构造函数 constructor(name: string) { super(name) } play() { console.log('我就喜欢玩') } } // 实例化对象 const per = new Person('大蛇丸') // 类的外部可以访问类中的属性成员 console.log(per.name) per.eat() })()
抽象类
abstract 开头的类是抽象类
抽象类不能用来创建对象,抽象类就是专门用来继承的类
abstract class Person { // readonly只读 readonly name = "hhh" static age = "aaa" say() { console.log('say方法') } }
类配合接口的实用
// 类 类型: 类的类型,类的类型可以通过接口实现 (() => { // 定义一个接口 interface IFly { // 该方法没有任何的实现(方法中什么都没有) fly() } // 定义一个类型,这个类的类型就是上面定义的接口(实际上也可以理解为,IFly接口约束了当前的这个Person类) class Person implements IFly { fly() { console.log('我会飞了') } } // 实例化对象 const person = new Person() person.fly() // 定义一个接口 interface ISwim { swim() } //定义一个类,这个类的类型就是IFly和ISwim(档期那这个类可以实现多个接口,一个类同时也可以被多个接口进行约束) class Person2 implements IFly, ISwim { fly() { console.log('我会飞2') } swim() { console.log('我会游泳啦2') } } // 实例化对象 const person2 = new Person2() person2.fly() person2.swim() // 总结类可以通过接口的方式,来定义档期那这个类的类型 // 类可以实现一个接口,类也可以实现多个接口,要注意,接口中的内容都要真正的实现 // 定义了一个接口,继承其他的多个接口 interface IMyFlyAndSwim extends IFly, ISwim { } // 定义一个类,直接实现IMyFlyAndSwim这个接口 class Person3 implements IMyFlyAndSwim { fly() { console.log('我会飞3') } swim() { console.log('我会游泳啦3') } } const person3 = new Person3() person3.fly() person3.swim() // 总结:接口和接口之间叫继承(使用的是extends关键字),类和接口之间叫实现(使用的是implements) })()
类的继承
// 继承:类与类之间的关系 // 继承后类与类之间的叫法: // A类继承了B这个类,那么此时A类叫子类,B类叫基类 // 子类 ---->派生类 // 基类 ---->超类(父类) (() => { // 定义一个类:作为基类(超类/父类) class Person { // 定义属性 name: string //名字 age: number //年龄 gender: string //性别 // 定义构造函数 constructor(name: string, age: number, gender: string) { // 更新属性数据 this.name = name this.age = age this.gender = gender } // 定义实例方法 sayHi(str: string) { console.log(`我是:${this.name},${str}`) } } // 定义一个类,继承自Person class Student extends Person { constructor(name: string, age: number, gender: string) { // 调用的是父类中的构造函数,使用的是super super(name, age, gender) } // 可以调用父类中的方法 sayHi() { console.log('我是学生类中的sayHi方法') // 调用父类中的sayHi方法 super.sayHi('哈哈') } } // 实例化Person const person = new Person('夏明', 89, '男') person.sayHi('嘎嘎') // 实例化Student const stu = new Student('小红', 45, '女') stu.sayHi() // 总结:类和类之间如果要有继承关系,需要使用extends关键字 // 子类中可以调整父类中的构造函数,使用的是super关键字(包括调用父类中的实例方法,也可以使用super) // 子类也可以重写父类的方法 })()
多态
// 多态:父类型的引用指向了子类型的对象,不同类型的对象针对相同的方法,产生了不同的行为 (() => { // 定义一个父类 class Animal { // 定义一个属性 name: string // 定义一个构造函数 constructor(name: string) { // 更新属性值 this.name = name } // 实例方法 run(distance: number = 0) { console.log(`跑了${distance}米这么元的距离`, this.name) } } // 定义一个子类 class Dog extends Animal { // 构造函数 constructor(name: string) { // 调用父类的构造函数,实现子类中属性的初始化操作 super(name) } // 实例方法,重写父类中的实列方法 run(distance: number = 5) { console.log(`跑了${distance}米这么元的距离`, this.name) } } // 定义一个子类 class Pig extends Animal { // 构造函数 constructor(name: string) { // 调用父类的构造函数,实现子类中属性的初始化操作 super(name) } // 实例方法,重写父类中的实列方法 run(distance: number = 10) { console.log(`跑了${distance}米这么远的距离`, this.name) } } // 实例化父类对象 const ani: Animal = new Animal('动物') ani.run() // 实例化子类对象 const dog: Dog = new Dog('大黄') // 实例化子类对象 const pig: Pig = new Pig('八戒') pig.run() // 父类和子类的关系:父子关系,此时,父类类型创建子类的对象 const dog1: Animal = new Dog('小黄') dog1.run() const pig1: Animal = new Dog('小猪') pig1.run() // 该函数需要的参数是Animal类型的 function showRun(ani: Animal) { ani.run } showRun(dog1) showRun(pig1) })()
泛型
在定义函数或是类时,如果遇到类型不明确就可以使用泛型(默认大写)
function fn<K>(a: K): K { return a; } // 1,可以直接调用,ts自动对类型进行推断 let result1 = fn(10); // 2 指定泛型 let result = fn<string>('hello')
泛型可以同时使用多个
function fn2<T, K>(a: T, b: K): T { console.log(b) return a } let result3 = fn2<number, string>(1, '1')
限制泛型的类型
T extends Inter表示泛型T必须是Inter的实现类(子类)
interface Inter { length: number } function fn3<T extends Inter>(a: T): number { return a.length } fn3('123')