typescript中的数据类型
-
布尔类型(boolean)
-
数字类型(number)
-
字符串类型(string)
-
数组类型(array)
第一种定义数组的方式:
let arr:number[]=[1,2,3,4,5]
第二种定义数组的方式:
let arr:Array<number>=[1,2,3,4,5]
-
元组类型(tuple)
let arr:[string,number,boolean]=["ts",3.18,true]
相当于js中的var arr=["ts",3.18,true]
-
枚举类型(enum)
enum Flag { success=1,error=-1 } var f:Flag=Flag.success console.log(f)//1
enum Color{ red,blue=5,orange } var a:Color=Color.red var b:Color=Color.blue var c:Color=Color.orange //枚举项没有赋值的话输出的是索引 console.log(a) //0 console.log(b) //5 console.log(c) //6
-
任意类型(any)
var a:any=123; a="qwe"; console.log(a); //qwe
-
void类型(一般用于定义方法时方法没有返回值)
//方法没有返回值 function run():void{ console.log("run"); } run();
//方法有返回值 function run():number{ return 123; } run();
-
undefined和null(never类型的子类型)
var num:number; console.log(num) //输出undefined 报错 var num:undefined; console.log(num) //输出undefined 未报错
//一个元素可能是number类型可能是null可能是undefined var num:number | null | undefined num=123; console.log(num) //123
-
never类型 (代表从不会出现的值)
var a:never; a=(()=>{ throw new Error("异常"); })()
typescript中的函数
ts中定义函数的方式
1.函数声明:
function run():string{
return "run"
}
2.函数表达式:
var fun1=function():number{
return 123;
}
ts中定义函数传参
function getInfo(name:string,age:number):string{
return `${name}---${age}`;
}
alert(getInfo("张三",20))
var getInfo=function(name:string,age:number):string{
return `${name}---${age}`;
}
alert(getInfo("张三",20))
ts中函数可选参数(es5中函数的实参和形参可以不一样,但是ts中必须一样并且可选参数必须写到参数的最后面)
function getInfo(name:string,age?:number):string{
if(age){
return `${name}---${age}`;
}else{
return `${name}---年龄保密`;
}
}
alert(getInfo("张三")) //ts中不传age实参的话需要在age形参后面加个?(并且age形参必须写到参数最后面)
ts中函数的默认参数(es5里面没法设置默认参数,es6和ts中都可以设置默认参数)
function getInfo(name:string,age:number=20):string{
if(age){
return `${name}---${age}`;
}else{
return `${name}---年龄保密`;
}
}
alert(getInfo("张三")) //张三---20
alert(getInfo("张三",30)) //张三---30
ts中函数的剩余参数
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));
ts中的重载(重载允许一个同名函数接受不同数量或类型的参数时,作出不同的处理)
function getInfo(name:string):string;
function getInfo(age:number):string;
function getInfo(str:any):any{
if(typeof str==='string'){
return "我叫"+str;
}else{
reurn "我年龄是"+str;
}
}
alter(getInfo("张三")); //我叫张三
alter(getInfo(20)); //我年龄是20
ts中的箭头函数
let sum = (a: number, b: number): number => {
return a + b;
}
console.log(sum(20,30)); //50
typescript中的类
定义类
class Person{
name:string;
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()); //李四
类的继承
class Person{
name:string;
constructor(name:string){
this.name=name;
}
run():string{
return `${this.name}在运动`
}
}
class Student extends Person{
constructor(name:string){
super(name); //初始化父类的构造函数
}
//子类重写父类方法
run():string{
return `${this.name}在运动-子类`
}
//子类定义自己的方法
work():void{
alert(`${this.name}在工作)
}
}
var s=new Student("张三");
alert(s.run()); //张三在运动-子类
类里面的修饰符
typescript里面定义属性的时候提供了三种修饰符
- public:公有 在类里面、子类、类外面都可以访问
- protected:保护类型 在类里面、子类都可以访问,在类外面无法访问
- private:私有 只能在类里面访问,子类、类外面都无法访问
静态属性和静态方法
class Person{
public name:string;
public age:number=20;
constructor(name:string){
this.name=name;
}
static sex="男";
//静态方法中无法直接调用类里面的非static属性,只能调用类里面的static属性
static print(){
alert("print方法"+Person.sex);
}
}
alert(Person.sex);
多态(父类定义一个方法不去实现,让继承它的子类去实现,每一个子类有不同的表现)(多态属于继承)
class Animal{
name:string;
constructor(name:string){
this.name=name;
}
//具体吃什么?继承它的子类去实现
eat(){
console.log("吃的方法");
}
}
class Dog extends Animal{
constructor(name:string){
super(name)
}
eat(){
return this.name+"吃骨头"
}
}
class Cat extends Animal{
constructor(name:string){
super(name)
}
eat(){
return this.name+"吃老鼠"
}
}
抽象类
-
抽象类是提供其他类继承的基类,不能直接被实例化
-
用abstract关键字定义抽象类和抽象方法,抽象类中的抽象方法不包含具体实现并且必须在派生类中实现
-
抽象方法只能放在抽象类中
abstract class Animal{ public name:string; constructor(name:string){ this.name=name; } abstract eat():any; run(){ console.log("跑的方法"); } } class Dog extends Animal{ constructor(name:any){ super(name) } //抽象类的子类必须实现抽象类中的抽象方法,非抽象方法可以不实现 eat(){ return this.name+"吃骨头" } } var d=new Dog("小黑"); d.eat();
typescript中的接口
接口的作用:在面向对象编程中,接口是一种规范的定义,它定义了行为和动作的规范,在程序设计中,接口起到了一种限制和规范的作用
-
属性接口
interface FullName{ firstName:string; secondName:string; } function printName(name:FullName){ console.log(name.firstName+"--"+name.secondName) } //传入的参数必须包含firstName、secondName var obj={ firstName:"张", secondName:"三", age:20 } printName(obj)
-
可选属性接口
interface FullName{ firstName:string; secondName?:string; } function printName(name:FullName){ console.log(name) } printName({ firstName:"张" })
-
函数类型接口(对函数传入的参数以及返回值进行约束)
//加密的函数类型接口 interface encrypt{ (key:string,value:string):string; } var md5:encrypt=function(key:string,value:string):string{ //模拟操作 return key+value; } console.log(md5("name","张三"));
-
可索引接口(对数组、对象的约束)
//对数组的约束 interface UserArr{ [index:number]:string } var arr:UserArr=["aaa","bbb"]; console.log(arr[0]); //对对象的约束 interface UserObj{ [index:string]:string } var arr:UserObj={ name:"张三" }
-
类类型接口(对类的约束和抽象类有点相似)
interface Animal{ name:string; eat(str:string):void; } class Dog implements Animal{ name:string; constructor(name:string){ this.name=name; } eat(food:string){ console.log(this.name+'吃'+food) } } var d=new Dog("小黑"); d.eat("骨头");
-
接口扩展(接口可以继承接口)
interface Animal{ eat():void; } interface Person extends Animal{ work():void; } class Student implements Person{ public name:string; constructor(name:string){ this.name=name; } eat(){ console.log(this.name+"喜欢吃包子") } work(){ console.log(this.name+"写代码"); } } var s=new Student("小明"); s.eat(); s.work();
typescript中的泛型
泛型:我们不仅要创建一致的定义良好的API,同时也要考虑可重用性。组件不仅能够支持当前的数据类型同时也能支持未来的数据类型,这在创建大型系统时提供了十分灵活的功能。像java这样的语言中,可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据,这样用户就可以以自己的数据类型来使用组件。通俗理解:泛型就是解决类、接口、方法的复用性,以及对不特定数据类型的支持
//设计同时返回string类型和number类型
function getData1(value:number):number{
return value;
}
function getData2(value:string):string{
return value;
}
//可以看出使用这种方式明显代码冗余
function getData(value:any):any{
return "哈哈哈";
}
//any可以解决代码冗余问题但是any放弃了类型检查,传入的参数类型和返回的参数类型可以不一致
解决以上问题的方法就是使用泛型
//T表示泛型,具体什么数据类型是调用这个方法时决定的
function getData<T>(value:T):T{
return value;
}
getData<number>(123);
getData<string>("123");
-
泛型类
class Min<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 Min<number>(); m1.add(3); m1.add(4); m1.add(1); alert(m1.min()) //1 var m2=new Min<string>(); m1.add("a"); m1.add("b"); m1.add("c"); alert(m1.min()) //a
-
把类作为参数类型的泛型类
//操作数据库的泛型类 class MysqlDb<T>{ add(info:T):boolean{ console.log(info); return true; } } //定义一个User类 class User{ username:string|undefined; password:string|undefined; } var u=new User(); u.username="张三"; u.password="123"; //给User表增加数据 var Db=new MysqlDb<User>(); Db.add(u); //定义一个ArticleCate类 class ArticleCate{ title:string|undefined; desc:string|undefined; status:number|undefined; constructor(params:{ title:string|undefined; desc:string|undefined; status?:number|undefined; }){ this.title=params.title; this.desc=params.desc; this.status=params.status; } } var a=new ArticleCate({ title:"分类", desc:"111" }); //给ArticleCate表增加数据 var Db=new MysqlDb<ArticleCate>(); Db.add(a);
-
泛型接口
- 第一种定义泛型接口的方法
interface ConfigFn{ <T>(value:T):T; } var getData:ConfigFn=function<T>(value:T):T{ return value; } getData<string>("张三"); getData<number>(20);
- 第二种定义泛型接口的方法
interface ConfigFn<T>{ (value:T):T; } function getData<T>(value:T):T{ return value; } var myGetData1:ConfigFn<string>=getData; myGetData1("张三"); var myGetData2:ConfigFn<number>=getData; myGetData2(20);
ts封装统一操作数据库的底层类库
- 功能:定义一个操作数据库的库,支持Mysql、Mssql等数据库
- 要求Mysql、Mssql功能一样,都有add、update、delete、get方法
- 注意:约束统一的规范、以及代码重用
- 解决方案
- 约束统一的规范需要用到接口
- 代码重用需要用到泛型
ts中的命名空间
命名空间:在代码量较大的情况下,为了避免各种变量命名相冲突,可将相似功能的函数、类、接口等放置到命名空间内
//animal.ts
export namespace A{
interface Animal{
name:string;
eat(str:string):void;
}
export class Dog implements Animal{
name:string;
constructor(name:string){
this.name=name;
}
eat(food:string){
console.log(this.name+'吃'+food)
}
}
}
//index.ts
import {A} from './modules/animal';
var d=new A.Dog("小黑");
d.eat("骨头")
ts中的装饰器
装饰器:是一种特殊类型的声明,它能够被附加到类、属性、方法或参数上,可以修改类的行为。通俗的讲装饰器就是一个方法,可以注入到类、属性、方法或参数上来扩展类、属性、方法或参数的功能
装饰器写法:普通装饰器(无法传参)、装饰器工厂(可传参)
常见装饰器:类装饰器、方法装饰器、属性装饰器、参数装饰器
-
类装饰器 ——普通装饰器(无法传参)
function logClass(params:any){ //params就是当前类 console.log(params); params.prototype.apiUrl="动态扩展的属性"; params.prototype.run=function(){ console.log("我是一个run方法"); } } @logClass class HttpClient{ constructor(){ } getData(){ } } var http:any=new HttpClient(); console.log(http.apiUrl); console.log(http.run());
-
类装饰器——装饰器工厂(可传参)
function logClass(params:string){ return function(target:any){ //params就是http://www.itying.com/api console.log(params); //target就是HttpClient这个类 console.log(target); params.prototype.apiUrl=params; } } @logClass("http://www.itying.com/api") class HttpClient{ constructor(){ } getData(){ } } var http:any=new HttpClient(); console.log(http.apiUrl);
-
类装饰器——应用于构造函数
function logClass(target:any){ return class extends target{ apiUrl:any="我是修改后的apiUrl"; getData(){ this.apiUrl=this.apiUrl+"——"; console.log(this.apiUrl); } } } @logClass class HttpClient{ public apiUrl:string | undefined; constructor(){ this.apiUrl="我是构造函数里面的apiUrl" } getData(){ console.log(this.apiUrl); } } var http=new HttpClient(); http.getData();//我是修改后的apiUrl——
-
属性装饰器
function logProperty(params:any){ return function(target:any,attr:any){ //target就是HttpClient这个类的原型对象 console.log(target); //attr就是url属性 console.log(attr); target[attr]=params; } } class HttpClient{ @logProperty("http://itying.com") pulic url:any | undefined constructor(){ } getData(){ console.log(this.url); } } var http=new HttpClient(); http.getData();
-
方法装饰器(它会被应用到方法的属性描述符上,可以用来监视,修改或替换方法定义)
方法装饰器会在运行时传入3个参数:
- 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象
- 方法的名字
- 方法的属性描述符
function get(params:any){ return function(target:any,methodName:any,desc:any){ //target就是HttpClient这个类的原型对象 console.log(target); //methodName就是getData方法的名字 console.log(methodName); console.log(desc); } } class HttpClient{ pulic url:any | undefined constructor(){ } @get("http://www.itying.com") getData(){ console.log(this.url); } }
-
方法参数装饰器
参数装饰器会在运行时被当作函数被调用,可以使用参数装饰器为类的原型增加一些元素数据
参数装饰器会在运行时传入3个参数:
- 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象
- 方法的名字
- 参数在函数参数列表中的索引
function logParams(params:any){ return function(target:any,methodName:any,paramsIndex:any){ console.log(params);//id //target就是HttpClient这个类的原型对象 console.log(target); //methodName就是getData方法的名字 console.log(methodName); //paramsIndex就是参数在函数参数列表中的索引 console.log(paramsIndex); } } class logParams{ pulic url:any | undefined constructor(){ } getData(@logParams("id") uid:any){ console.log(uid);//123 } } var http=new logParams(); http.getDta(123);
-
装饰器执行顺序
属性>方法>方法参数>类(如果有多个同样的装饰器,它会先执行后面的)