ts类与兼容性相关
2021/5/22 18:28:30
本文主要是介绍ts类与兼容性相关,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
1.类
// ts和ES6区别, 需要先定义实例属性, 才能够使用实例属性 class Person { name:string; // 和es6的区别:需要先定义实例属性,才能够使用实例属性,如果没定义就使用会报错 age:number; constructor(name:string,age:number){ this.name = name; this.age = age; } say():void{ console.log(`我的名字是${this.name}年龄是${this.age}`); } static food:string; static eat():void{ console.log(this); // 当前this指向父类,所以可以调用food console.log(`我的食物是${this.food}`); } } new Person('小田',22).say(); // 我的名字是小田 Person.food = '甜筒'; Person.eat(); // 我的食物是甜筒 class Student extends Person { book:string; constructor(name:string,age:number,book:string){ super(name,age); this.book = book console.log(Student.food); // 这里是可以进行打印的,打印的是Person里的静态属性food } say():void{ console.log(`student里的我的名字是${this.name}年龄是${this.age}数${this.book}`); } static sayfood():void{ console.log(this.food) } } Student.food = 'dwadwadwa'; Student.sayfood();
2.类属性修饰符
// public(公开的) : // 如果使用public来修饰属性, 那么表示这个属性是公开的 // 可以在类的内部使用, 也可以在子类中使用, 也可以在外部使用 // protected(受保护的) : // 如果使用protected来修饰属性, 那么表示这个属性是受保护的 // 可以在类的内部使用, 也可以在子类中使用 // private(私有的) : // 如果使用private来修饰属性, 那么表示这个属性是私有的 // 可以在类的内部使用 // readonly(只读的) : class Person { public name:string; // 默认情况下就是public的 protected age:number; private gender:string; constructor(name:string, age:number, gender:string){ this.name = name; this.age = age; this.gender = gender; } say():void{ console.log(`name=${this.name},age=${this.age},gender=${this.gender}`); } } class Student extends Person{ constructor(name:string, age:number, gender:string){ super(name,age,gender); } say():void{ // console.log(`name=${this.name}`); // name=xt // console.log(`age=${this.age}`); // age=11 // console.log(`gender=${this.gender}`); // Error 私有的属性,继承不可以访问 } } let p = new Student('xt',11, '1'); p.say();
3.类只读属性
// 类的只读属性: // 可以在constructor内赋值多次,但是不能在实例的方法中更改值,也不能在外部实例中更改属性 class Person { readonly name:string; constructor(name:string){ this.name = name; this.name =' 11111'; } } let p = new Person('dwadw'); console.log(p.name); // p.name ='dwadwadwa'; // 无法分配到 "name" ,因为它是只读属性。
4.类方法修饰符
class Person { name:string; age:string; gender:string; constructor(name:string,age:string,gender:string){ this.name = name; this.age = age; this.gender = gender; } public sayName():void{ console.log(`person我的名字是${this.name}`); } protected sayAge():void{ console.log(`person我的年龄是${this.age}`); } private sayGender():void{ console.log(`person我的性别是${this.gender}`); } } class Student extends Person{ constructor(name:string,age:string,gender:string){ super(name,age,gender); } say():void{ // this.sayName(); // person我的名字是小田 // this.sayAge(); // person我的年龄是22 this.sayGender(); // 属性“sayGender”为私有属性,只能在类“Person”中访问。ts(2341) } } let p = new Student('小田','22','男'); let p1 = new Person('111', '34', '1'); p.say(); p1.sayName(); p1.sayAge(); // 属性“sayAge”受保护,只能在类“Person”及其子类中访问。ts(2445) p1.sayGender(); // 属性“sayGender”为私有属性,只能在类“Person”中访问。ts(2341)
5.类可选参数
// 类可选属性 // 和接口的可选属性一样,可传可不传的属性 // 注意: // 1.如果在类中,定义属性时,如果只定义了类型,没有初始化值,那么在constructor中必须赋值,不然会报错 // 2.如果定义属性时,初始化值,就不用在构造器中使用赋值,不会报错 class Person { name:string; age?:string; constructor(name:string,age?:string){ this.name = name; this.age = age; } setname(name:string,age:string):void{ this.name = name; this.age = age; } } let p = new Person('laotianwy'); // Person { name: 'laotianwy', age: undefined } p.setname('xiaotian','23'); // Person { name: 'xiaotian', age: '23' } // 需求: 有一个基类, 所有的子类都需要继承于这个基类, 但是我们不希望别人能够通过基类来创建对象 class Person { name:string; age:number; gender:number; protected constructor(name:string,age:number,gender:number){ this.name = name; this.age = age; this.gender = gender; } say():void{ console.log(`我的名字是${this.name},我的年龄是${this.age},我的性别是${this.gender}`); } } class Student extends Person{ constructor(name:string,age:number,gender:number){ super(name,age,gender); } } let p = new Person('name',11,22); // Error let p1 = new Student('name',11,22);
6.类构造器参数使用public
// 如果在constructor中参数使用了public修饰,那么就不用在声明实例属性了 class Student { constructor(public name:string,public age:string){ } } new Student('xxxxxxx','22222'); // Student { name: 'xxxxxxx', age: '22222' }
7.类的可选属性
// 类可选属性 // 和接口的可选属性一样,可传可不传 在实例属性内加 ? class Person { name:string; age?:number; constructor(name:string,age?:number){ this.name = name; this.age = age; } } new Person('laotian'); class Student { constructor(public name:string,public age?:number){ } } let p = new Student('laitan'); // Student { name: 'laitan', age: undefined }
8.存储器
// 存储器 // 通过getters/setters来截取对对象成员的访问 class Person { _age:number = 0; private _name:number = 0; set age(val:number){ console.log(val); if(val < 0 ){ throw new Error('人的年龄不能小于0'); } this._age = val; } get age():number{ console.log('进入了get age 的方法'); return this._age; } set name(val:number){ console.log(val,'name'); this._age = val; } get name():number{ return this._name; } } let p = new Person(); p.age = 42; // p.age(42) console.log(p.age); // p.age();
9.抽象类
// 抽象类 // 1.抽象类专门用于定义那些不希望被外界直接创建的类 // 2.抽象类一般用于定义基类 // 3.抽象类和接口一般用于约束子类 // 4.区别: // 1.接口中只能定义约束,不能定义具体实现 // 2.抽象类即可以定义约束,又可以定义具体实现 // 3.抽象类不能创建实例, // 4.抽象类的属性如果是abstract修饰,那么不能够继承,只能再次在子类中再次声明 abstract class Person1{ abstract name:string; abstract say():void; eat():void{ console.log(`${this.name}正在吃饭`); } } // let p1 = new Person1(); // Error 无法创建抽象类的实例。ts(2511) // 非抽象类“Student1”不会实现继承自“Person1”类的抽象成员“name”。ts(2515) // 非抽象类“Student1”不会实现继承自“Person1”类的抽象成员“say”。ts(2515) class Student1 extends Person1{ name:string = 'xiaotian'; say():void{ console.log(`我的名字是${this.name}`) } } let ab1 = new Student1(); ab1.say(); // 我的名字是xiaotian ab1.eat(); // xiaotian正在吃饭
10.类与接口
// 类和接口 // 1.类 实现 接口:使用implements关键字实现 // 只要实现某一个接口,那么就必须实现接口当中所有的属性和方法 interface PersonFace{ name:string; say():void; } class Person implements PersonFace { name:string; constructor(name:string) { this.name = name; } say():void{ } } // 2.接口继承类 // 1.只要这个接口继承了某个类,那么就会继承这个类的所有的属性和方法 // 2.但是只会继承属性和方法的声明,不会继承属性和方法的实现 // 注意:如果接口继承的类中包含了protected的属性和方法,那么就只有这个类的子类才能实现这个接口 class Honey { name:string = 'xt'; age:number = 22; say():void{ console.log(`我的名字是${this.name}年龄是${this.age}`); } } interface PersonHoneyInterface extends Honey{ gender:string; } // 第一种方式类实现接口 class StudentHoney implements PersonHoneyInterface { name:string = 'xiaotian'; age:number = 21; gender:string = 'nan'; say():void{ console.log(`大娃大娃多哇我`); } } // 第二种方式类实现接口 class StudentHoney1 extends Honey implements PersonHoneyInterface { gender:string = 'dwadwa'; // 如果没有gender属性会报错 } let stu1 = new StudentHoney1(); // 如果 "StudentHoney1" 中缺少属性 "gender",但类型 "PersonHoneyInterface" 中需要该属性。就会Error console.log(stu1);
11.类和泛型
// 类和泛型 // 泛型类 class Student<t> { arr:t[] = []; add(values:t):void{ this.arr.push(values); } all():t[]{ return this.arr; } } let initStudent = new Student<number>(); initStudent.add(1); initStudent.add(2); initStudent.add(3); initStudent.all(); // [ 1, 2, 3 ]
12.同名接口合并现象
// 接口合并现象 // 当我们定义了多个同名的接口,多个接口的内容会自动合并 // 如果使用类实现的话那么就得全部实现,要不然会报错 interface TestFace{ name:string; } interface TestFace{ age:number; } interface TestFace{ gender:boolean; } // 如果实现的话那么就得全部实现 要不然会报错 class Person implements TestFace{ name:string = 'dwadw'; age:number = 2123; gender:boolean = true; }
13.枚举-字符串枚举和数字枚举
// 数字枚举和字符串枚举 // 1.数字枚举 // 1.数字枚举默认从0开始,数字枚举的取值可以是字面量也可以是常量,也可以是结算的结果 // 2.如果使用常量给前面的枚举赋值了,那么后面的枚举值也需要手动的赋值 // 3.如果使用计算结果给前面的枚举赋值,那么后面的枚举值也需要手动的赋值 // 注意:如果使用了常量或者计算属性那么是可以通过索引进行获取枚举的 // 2.字符串枚举值 // 1.如果使用字符串枚举值给前面的枚举值赋值了,那么后面的枚举值也必须手动赋值 // 2.和数字枚举不一样,字符串枚举不能使用常量和计算属性给枚举赋值 // 3.虽然字符串枚举不能够使用常量或者计算属性赋值,但是可以使用内部的其他枚举来赋值 // 注意:如果使用了字符串枚举那么就不能通过索引进行获取了 enum Gender{ Male, Female } console.log(Gender.Male); // 0 console.log(Gender.Female); // 1 // 2.数字枚举注意点: // 1.数字枚举默认从0开始,数字枚举的取值可以是字面量也可以是常量,也可以是结算的结果 // 2.如果使用常量给前面的枚举赋值了,那么后面的枚举值也需要手动的赋值 // 3.如果使用计算结果给前面的枚举赋值,那么后面的枚举值也需要手动的赋值 // 注意:如果使用了常量或者计算属性那么是可以通过索引进行获取枚举的 const num = 55; function getNum(){ return 999; } enum SexList{ // male = 6, man = num, female = getNum() } console.log(SexList.man); // 55 console.log(SexList[55]); // male console.log(SexList.female); // 999 // 3.枚举反向映射 // 1.可以根据枚举值获取到原始值 // 2.也可以根据原始值获取到枚举值 enum gender1{ male, female } console.log(gender1.male); // 0 console.log(gender1[0]); // male // 3.字符串枚举值 // 1.如果使用字符串枚举值给前面的枚举值赋值了,那么后面的枚举值也必须手动赋值 // 2.和数字枚举不一样,字符串枚举不能使用常量和计算属性给枚举赋值 // 3.虽然字符串枚举不能够使用常量或者计算属性赋值,但是可以使用内部的其他枚举来赋值 // 注意:如果使用了字符串枚举那么就不能通过索引进行获取了 const str1 = 'laotian'; function getStr(){ return 'abc;' } enum gender2{ // male= 'www.baidu.com', // male = str1, // Error // male = getStr() // Error female = 'www.xinlang.com', yao = female } console.log(gender2.female); // www.xinlang.com console.log(gender2.yao); // www.xinlang.com // console.log(gender2['www.xinlang.com']); // 如果使用了字符串枚举那么就不能通过索引进行获取了
14.枚举成员类型和联合类型
// 枚举成员类型 // 1.可以把枚举成员当做类型使用 enum Gender{ male = 'www.baidu.com', female = 'www.laotian.com', } interface TestInterface{ age:Gender.male } class Person implements TestInterface{ // age:Gender.male = Gender.male; // age:Gender.female; // Error类型不匹配报错 // age:Gender.male = 0; // Error不能将类型“0”分配给类型“Gender.male”。原因是枚举值是字符串,如果枚举值是数字那么就可以进行赋值是0 age:Gender.male = Gender.male; // age:Gender.male = 'dwadwa'; // Error 如果是字符串枚举,只能赋值枚举成员的值,上面就不会报错 age:Gender.male = true; // Error 如果赋值别的值,会报错 } // 2.联合枚举类型 // 1.什么是联合类型 // 联合数据类型就是将多种数据类型通过|链接起来 // 可以把枚举类型当做一个联合类型来使用 let value:(number|string); // (number|string)联合类型,既可以存数字又可以存字符串 enum Gender1 { Male, Female } interface testInterface{ age:Gender1 // age:(Gender1.Male|Gebder1.Female) } class Person1 implements testInterface { // age = 0; // age = Gender1.Male; age = Gender1.Female; }
15.运行时枚举
// 运行时枚举 // 1.枚举在编译后是一个真实存储的对象,所以可以在运行时使用 // 2.而像接口这种只是用来约束做静态检查的代码,编译之后是不存在的 interface TestInterface{ name:string; age:number; } enum Gender{ male, female } // 常量枚举 // 1.普通枚举和常量枚举的区别 // 1.普通枚举会生成真实存在的对象 // 2.常量枚举不会生成真实存在的对象,而是利用枚举成员的值直接替换使用到的地方 var Gender1; ( function(Gender1){ Gender1[Gender1['male'] = 0] = 'male'; Gender1[Gender1['female'] = 1] = 'female'; } )(Gender1 || (Gender1 = {})) enum Gender100{ male, female } console.log(Gender100.male === 0);// true const enum Gender200{ male, female } console.log(Gender200.male === 0); // true
16.类型推断
// 类型推断 // 1.什么是类型推断 // 1.不用明确告诉编译器是什么类型,编译器就知道是什么类型 // 2.根据初始化值自动推断 // 1.如果是先定义再初始化,那么是无法自动推断的 // 2.如果是定义的同时初始化,那么ts就会自动进行类型推断 // 3.根据上下文类型自动推断 // 4.推荐一篇文章:https://blog.csdn.net/u011127019/article/details/73867203?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522162167388616780366515120%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=162167388616780366515120&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_v2~rank_v29-1-73867203.pc_search_result_hbase_insert&utm_term=typescript+%E4%BB%80%E4%B9%88%E6%98%AF%E5%85%BC%E5%AE%B9%E6%80%A7&spm=1018.2226.3001.4187 let values; values = 2222; values = 'dwadwa'; let values1 = 2132; // values1 = 'dwadwad'; // Error let arr1 = [1,'a']; // (number|string)[] // arr1 = ['dwafaw',2123,'dwadw',true] // Error 前面的没事,最后一个true有问题 不能将类型“boolean”分配给类型“string | number”。ts(2322) // 根据上下文类型类型自动推断 window.onmousedown = (event) => { console.log(event.target); }
17.类型兼容性
// 类型兼容性 // 1.基本兼容性,interface与变量兼容 interface TestInterface{ name:string } let p1 = {name:'laotian'}; let p2 = {age:22}; let p3 = {name:'laotian',age:22}; let t:TestInterface; t = p1; t = p2; // Error t = p3; // 可多不可少 interface Test1Interface{ name:string; children:{ age:number } } let p4 = {name:'laotian',children:{age:22}} let p5 = {name:'laotian',children:{age:'age'}} let t2:Test1Interface; t2 = p4; t2 = p5; // Error 会递归检查,age是字符串类型
18.函数兼容性
// 函数兼容性:可以把少的赋值给多的, // 参数个数 let fn1 = (x:number,y:number) => {}; let fn2 = (x:number) => {}; fn1 = fn2; // fn2 = fn1; // Error 会报错 不能将类型“(x: number, y: number) => void”分配给类型“(x: number) => void”。ts(2322) // 参数类型:必须一模一样 let f1 = (x:number) => {}; let f2 = (x:number) => {}; let f3 = (x:string) => {}; f1 = f2; // f1 = f3; // Error 类型必须一样 不能将类型“(x: string) => void”分配给类型“(x: number) => void”。参数“x”和“x” 的类型不兼容。不能将类型“number”分配给类型“string”。 f2 = f1; // 返回值类型:返回的类型必须一样 let t1 = ():number => 123; let t2 = ():number => 123; let t3 = ():string => '123'; t1 = t2; t2 = t1; // t1 = t3; // Error 返回的类型必须一样 // 函数的双向斜变 // 1.参数的双向斜变 let change1 = (x:(number|string)) => {}; let change2 = (x:number) => {}; change1 = change2; // 不能将类型“(x: number) => void”分配给类型“(x: (number | string)) => void”。参数“x”和“x” 的类型不兼容。不能将类型“string | number”分配给类型“number”。 不能将类型“string”分配给类型“number”。 change2 = change1; // 2.返回值双向斜变 // 1.可以将返回值是具体类型的赋值给联合类型的 // 2.不能将返回值是联合类型的赋值给具体类型的 let return1 = (x:boolean):(number|string) => x ? 123:'123'; let return2 = (x:boolean):number => 456; return1 = return2; // 可以将返回值是具体类型的赋值给联合类型的 return2 = return1; // 不能将返回值是联合类型的赋值给具体类型的 // 函数的重载 // 1.不能讲重载少的,赋值给重载多的, // 2.可以将重载多的,赋值给重载少的 function add(x:number,y:number):number; function add(x:string,y:string):string; function add(x,y){ return x+y; } function sub(x:number,y:number):number; function sub(x,y):number{ return x-y; } let add1 = add; let sub1 = sub; add1 = sub1; // 不能将类型“(x: number, y: number) => number”分配给类型“{ (x: number, y: number): number; (x: string, y: string): string; }”。参数“x”和“x” 的类型不兼容。不能将类型“string”分配给类型“number”。 sub1 = add1;
19.枚举兼容性
// 枚举兼容性 // 1.数字枚举和数字枚举兼容 // 2.数字枚举和数字枚举不兼容,不能兼容别的枚举 // 3.字符串枚举和字符串不兼容 // 数字枚举和数字枚举兼容 enum Gender{ male, female } let value:Gender; value = Gender.male; value = 0; // 数字枚举和数字枚举不兼容 enum Gender1{ male, female } enum Gender2{ male, female } let val1:Gender1; val1 = Gender1.male; // val1 = Gender2.male; // Error 不能将类型“Gender2.male”分配给类型“Gender1”。ts(2322) // 字符串枚举和字符串不兼容 enum StringEnum{ male = 'abc', female = 'def' } let valueStr:StringEnum; valueStr = StringEnum.male; valueStr = 'abc'; // Error 不能将类型“"abc"”分配给类型“StringEnum”。ts(2322)
这篇关于ts类与兼容性相关的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-09-28微服务架构中API版本控制的实践
- 2024-09-28AI给的和自己写的Python代码,都无法改变输入框的内容,替换也不行
- 2024-09-27Sentinel配置限流资料:新手入门教程
- 2024-09-27Sentinel配置限流资料详解
- 2024-09-27Sentinel限流资料:新手入门教程
- 2024-09-26Sentinel限流资料入门详解
- 2024-09-26Springboot框架资料:初学者入门教程
- 2024-09-26Springboot框架资料详解:新手入门教程
- 2024-09-26Springboot企业级开发资料:新手入门指南
- 2024-09-26SpringBoot企业级开发资料新手指南