TypeScript(数据类型、函数、类、接口、泛型)
TypeScript 设计目标是开发大型应用,它可以编译成纯 JavaScript,编译出来的 JavaScript 可以运行在任何浏览器上。
JavaScript 与 TypeScript 的区别
TypeScript 是 JavaScript 的超集,支持 ECMAScript 6 标准,扩展了 JavaScript 的语法,因此现有的 JavaScript 代码可与 TypeScript 一起工作无需任何修改,TypeScript 通过类型注解提供编译时的静态类型检查。
TypeScript 可处理已有的 JavaScript 代码,并只对其中的 TypeScript 代码进行编译。
一、typeScript中的数据类型
typescript中为了使编写的代码更规范,更有利于维护,增加了类型校验,在typescript中主要给我们提供了以下数据类型
1.1 布尔类型(boolean) let flag: boolean = true;
1.2 数字类型(number) let num: number = 6;
1.3 字符串类型(string) let str: string = “str”;
1.4 数组类型(array)
var arr:number[]=[11,22,33];
var arr:Array=[11,22,33];
var arr3:any[]=[‘131214’,22,true];
1.5 元组类型(tuple)
属于数组的一种,例如数组中既可有string、又可有number
let arr:[number,string]=[123,‘this is ts’];
缺点是,必须指定的位置对用指定的类型,后面这种情况会用到任意类型 any
1.6 枚举类型(enum)
一般用于表示错误码,为了易读性强,单词可以用引号也可以不用,一般不写就是下表(从0开始,但是如果前一个有值,则从前一个的下表往后默认赋值)
enum Err {'undefined'=-1,'null'=-2,'success'=1};
var e:Err=Err.success;
console.log(e);
1.7 任意类型(any)
场景:比如获取dom节点,ts中不加类型会提示dom节点是object,但是类型没object,给了也会报错,
这种情况就需要用到any类型。
1.8 null 和 undefined 其他(never类型)数据类型的子类型
一个元素可能是 number类型 可能是null 可能是undefined
var num:number | null | undefined;
1.9 void类型
typescript中的void表示没有任何类型,一般用于定义方法的时候方法没有返回值。
无返回值
function run():void{
console.log('run')
}
run();
有返回值
function run():number{
return 123;
}
run();
1.10 never类型 是其他类型 (包括 null 和 undefined)的子类型,代表从不会出现的值。
这意味着声明never的变量只能被never类型所赋值。
var a:undefined; a=undefined;
var b:null; b=null;
var a:never;
a=(()=>{
throw new Error('错误');
})()
但是这里也可以用any或者string代替,这里只是也可以用never
二、typeScript中的函数
2.1 函数的定义
es5定义函数的方法1函数声明法2匿名函数
ts中定义函数的方法
//函数声明法
function run():string{
return 'run';
}
//匿名函数
var fun2=function():number{
return 123;
}
ts中定义方法传参
function getInfo(name:string,age:number):string{
return `${name} --- ${age}`;
}
alert(getInfo('zhangsan',20));
//没有返回值的方法
function run():void{
console.log('run')
}
run();
2.2 函数的可选参数
es5里面方法的实参和行参可以不一样,但是ts中必须一样,如果不一样就需要配置可选参数
function getInfo(name:string,age?:number):string{
if(age){
return `${name} --- ${age}`;
}else{
return `${name} ---年龄保密`;
}
}
注意:可选参数必须配置到参数的最后面
2.3 函数的默认参数
es5里面没法设置默认参数,es6和ts中都可以设置默认参数
function getInfo(name:string,age:number=20):string{
if(age){
return `${name} --- ${age}`;
}else{
return `${name} ---年龄保密`;
}
}
2.4 函数的剩余参数
三点运算符 接受新参传过来的值
function sum(...result:number[]):number{
var sum=0;
for(var i=0;i<result.length;i++){
sum+=result[i];
}
return sum;
}
alert(sum(1,2,3,4,5,6)) ;
function sum(a:number,b:number,...result:number[]):number{
var sum=a+b;
for(var i=0;i<result.length;i++){
sum+=result[i];
}
return sum;
}
alert(sum(1,2,3,4,5,6)) ;
2.5 函数重载
es5中出现同名方法,下面的会替换上面的方法
ts中的重载
function getInfo(name:string):string;
function getInfo(age:number):string;
function getInfo(str:any):any{
if(typeof str==='string'){
return '我叫:'+str;
}else{
return '我的年龄是'+str;
}
}
alert(getInfo('张三')); //正确
alert(getInfo(20)); //正确
alert(getInfo(true)); //错误写法
//可选
function getInfo(name:string):string;
function getInfo(name:string,age:number):string;
function getInfo(name:any,age?:any):any{
if(age){
return '我叫:'+name+'我的年龄是'+age;
}else{
return '我叫:'+name;
}
}
alert(getInfo('zhangsan')); //正确
alert(getInfo(123)); //错误
alert(getInfo('zhangsan',20)); //正确
重载的getInfo函数在调用的时候会进行正确的类型检查。
为了让编译器能够选择正确的检查类型,它与JavaScript里的处理流程相似。 它查找重载列表,尝试使用第一个重载定义。如果匹配的话就使用这个。 因此,在定义重载的时候,一定要把最精确的定义放在最前面。
注意,function getInfo(x): any并不是重载列表的一部分,
因此这里只有两个重载:一个是接收对象另一个接收数字。 以其它参数调用 getInfo会产生错误。
2.6、箭头函数 es6
this指向的问题 箭头函数里面的this指向上下文
三、typeScript中的类
首先说一下js中的继承
构造函数继承(call):可以继承构造函数中的属性和方法,但是没法继承原型链上的属性和方法
原型链实现继承:Web.prototype=new Person(),可以继承构造函数里面的属性和方法 也可以继承原型链上 面的属性和方法,但是 实例化子类的时候没法给父类传参
组合继承:需两种结合
function Web(name,age){
Person.call(this,name,age);
//可以继承构造函数里面的属性和方法、实例化子类可以给父类传参
}
Web.prototype=Person.prototype;//可以继承原型链上的属性和方法
当然还有其他一些继承,原型式继承、寄生式继承、寄生组合式继承,不一一介绍了。
接下类我们开始ts中的类
3.1 ts中类的定义
其实就是在es6的基础上加了类型检测
class Person{
name:string; //属性 前面省略了public关键词
constructor(name:string){ //构造函数 实例化类的时候触发的方法
this.name=name;
}
getName():string{
return this.name;
}
setName(name:string):void{
this.name=name;
}
}
var p=new Person('张三');
alert(p.getName());
p.setName('李四');
alert(p.getName());
3.2 ts中实现继承 extends、 super
其实就是在es6的基础上加了类型检测
class Web extends Person{
constructor(name:string){
super(name); /*初始化父类的构造函数*/
}
}
var w=new Web('李四');
alert(w.getName());
ts中继承的探讨 父类的方法和子类的方法一致时,以子类方法为主
3.3 ts中类里面的修饰符
typescript里面定义属性的时候给我们提供了 三种修饰符
public :公在当前类里面、 子类 、类外面都可以访问
protected:保护类型在当前类里面、子类里面可以访问 ,在类外部没法访问
private :私有 在当前类里面可以访问,子类、类外部都没法访问
属性如果不加修饰符 默认就是 公有 (public)
3.4 ts中的静态属性 静态方法
class Per{
public age:number=20;
//静态属性
static sex="男";
static print(){ /*静态方法 里面没法直接调用类里面的属性*/
alert('print方法'+this.sex); //报错
alert('print方法'+Per.sex); //需要此种方式调取静态属性
}
}
Per.print();
3.5 ts中的多态、抽象类
多态:父类定义一个方法不去实现,让继承它的子类去实现 每一个子类有不同的表现,多态属于继承
抽象类:它是提供其他类继承的基类,不能直接被实例化。用abstract关键字定义抽象类和抽象方法,抽象类中的抽象方法不包含具体实现并且必须在派生类中实现。abstract抽象方法只能放在抽象类里面,抽象类和抽象方法用来定义标准 。
abstract class Animal{
public name:string;
constructor(name:string){
this.name=name;
}
abstract eat():any; //抽象方法不包含具体实现并且必须在派生类中实现。
run(){
console.log('其他方法可以不实现')
}
}
// var a=new Animal() /*错误的写法*/
class Dog extends Animal{
//抽象类的子类必须实现抽象类里面的抽象方法
constructor(name:any){
super(name)
}
eat(){
console.log(this.name+'吃粮食')
}
}
var d=new Dog('小花花');
d.eat();
四、typeScript中的接口
接口的作用:在面向对象的编程中,接口是一种规范的定义,它定义了行为和动作的规范,在程序设计里面,接口起到一种限制和规范的作用。接口定义了某一批类所需要遵守的规范,接口不关心这些类的内部状态数据,也不关心这些类里方法的实现细节,它只规定这批类里必须提供某些方法,提供这些方法的类就可以满足实际需要。 typescrip中增加了更灵活的接口类型,包括属性、函数、可索引和类等。
4.1 属性类接口
对json的约束
function printLabel(labelInfo:{label:string}):void {
console.log('printLabel');
}
printLabel('hahah'); //错误写法
printLabel({name:'张三'}); //错误的写法
printLabel({label:'张三'}); //正确的写法
对批量方法进行约束
interface FullName{
firstName:string; //注意 ;结束
secondName:string;
}
function printName(name:FullName){
// 必须传入对象 firstName secondName
console.log(name.firstName+'--'+name.secondName);
}
printName('1213'); //错误
var obj={ /*传入的参数必须包含 firstName secondName*/
age:20,
firstName:'张',
secondName:'三'
;
printName(obj) //正确
如果不写obj对象当参数传入,而是直接写对象 printName({ firstName:‘张’,secondName:‘三’}),这时只能有firstName、secondName,否则报错
虽然上面不报错,但是当函数内部使用它时,就会报错,因为接口里面只约束了两
个字段,要使用其他的就会报错,这就是对批量方法进行约束,接口不仅传值约束,使用时也约束,所以还是老老实实按照接口来
接口 :可选属性 加?
interface FullName{
firstName:string;
econdName?:string;
}
function getName(name:FullName){ console.log(name) }
getName({
firstName:'firstName'
})
4.2 函数类型接口
对方法传入的参数 以及返回值进行约束 批量约束
加密的函数类型接口
interface encrypt{
(key:string,value:string):string;
}
var md5:encrypt=function(key:string,value:string):string{
//模拟操作
return key+value;
}
console.log(md5('name','zhangsan'));
var sha1:encrypt=function(key:string,value:string):string{
//模拟操作
return key+'----'+value;
}
console.log(sha1('name','lisi'));
4.3 可索引接口
数组、对象的约束 (不常用)
//可索引接口 对数组的约束
interface UserArr{
[index:number]:string
}
var arr:UserArr=['aaa','bbb'];/*正确*/
console.log(arr[0]);
var arr:UserArr=[123,'bbb']; /*错误*/
console.log(arr[0]);
//可索引接口 对对象的约束
interface UserObj{
[index:string]:string
}
var arr:UserObj={name:'张三'};
4.4 类类型接口
对类的约束 和 抽象类抽象有点相似
interface Animal{
name:string;
eat(str:string):void;
}
class Dog implements Animal{
name:string;
constructor(name:string){
this.name=name;
}
eat(){
console.log(this.name+'吃粮食')
}
}
var d=new Dog('小黑');
d.eat();
//-----------------
class Cat implements Animal{
name:string;
constructor(name:string){
this.name=name;
}
eat(food:string){
console.log(this.name+'吃'+food);
}
}
var c=new Cat('小花');
c.eat('老鼠');
4.5 接口扩展
接口可以继承接口
interface Animal{
eat():void;
}
interface Person extends Animal{
work():void;
}
class Web implements Person{
public name:string;
constructor(name:string){
this.name=name;
}
eat(){
console.log(this.name+'喜欢吃馒头')
}
work(){
console.log(this.name+'写代码');
}
}
var w=new Web('小李');
w.eat();
继承类实现接口
interface Animal{
eat():void;
}
interface Person extends Animal{
work():void;
}
class Programmer{
public name:string;
constructor(name:string){
this.name=name;
}
coding(code:string){
console.log(this.name+code)
}
}
class Web extends Programmer implements Person{
constructor(name:string){
super(name)
}
eat(){
console.log(this.name+'喜欢吃馒头')
}
work(){
console.log(this.name+'写代码');
}
}
var w=new Web('小李');
// w.eat();
w.coding('写ts代码');
五、typeScript中的泛型
泛型: 组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能。泛型就是解决 类 接口 方法的复用性、以及对不特定数据类型的支持(类型校验)。可以支持不特定的数据类型 要求:传入的参数和返回的参数一直,T表示泛型,有时候要求类型检测,但是返回任意类型,这也是泛型,只不过不常用
5.1 泛型函数
function getData<T>(value:T):T{
return value;
}
getData<number>(123);
getData<string>('1214231');
有时候要求类型检测,但是返回任意类型,这也是泛型,只不过不常用
function getData<T>(value:T):any{
return '2145214214';
}
getData<number>(123); //参数必须是number
getData<string>('这是一个泛型');
5.2 泛型类
类的泛型, any没有类型校验
class MinClas<T>{
public list:T[]=[];
add(value:T):void{
this.list.push(value);
}
min():T{
var minNum=this.list[0];
for(var i=0;i<this.list.length;i++){
if(minNum>this.list[i]){
minNum=this.list[i];
}
}
return minNum;
}
}
var m1=new MinClas<number>(); /*实例化类 并且制定了类的T代表的类型是number*/
m1.add(11);
m1.add(3);
m1.add(2);
alert(m1.min())
var m2=new MinClas<string>(); /*实例化类 并且制定了类的T代表的类型是string*/
m2.add('c');
m2.add('a');
m2.add('v');
alert(m2.min())
5.3 泛型接口
函数类型接口
interface ConfigFn{
(value1:string,value2:string):string;
}
var setData:ConfigFn=function(value1:string,value2:string):string{
return value1+value2;
}
setData('name','张三');
定义泛型接口的两种方法
//1、泛型接口
interface ConfigFn{
<T>(value:T):T;
}
var getData:ConfigFn=function<T>(value:T):T{
return value;
}
getData<string>('张三');
getData<string>(1243); //错误
//---------------------
//2、泛型接口
interface ConfigFn<T>{
(value:T):T;
}
function getData<T>(value:T):T{
return value;
}
var myGetData:ConfigFn<string>=getData;
myGetData('20'); /*正确*/
// myGetData(20) //错误
下一篇: Shiro应用(一)--- 单独使用
推荐阅读
-
Java 泛型示例 - 泛型方法,类,接口
-
.NET/C#如何判断某个类是否是泛型类型或泛型接口的子类型详解
-
深入解析C#中的泛型类与泛型接口
-
泛型约束:接口约束、new()构造函数约束、组合约束(即多种约束合并)
-
集合框架与泛型(二)——Map接口、Collections类和泛型
-
Typescript类型、接口、类、泛型综合使用
-
typescript(八)--ts中接口(可索引型、类类型)
-
typescript学习之二(类、泛型、接口等)
-
TypeScript(数据类型、函数、类、接口、泛型)
-
TS05 TS类型、接国、类、泛型综合使用-.TypeScript封装统一 操作Mysql Mongodb Mssq|l的底层类库