1.typescript下载 编译
npm install -g typescript
新建 index.ts
编译:tsc index.ts ; 会生成一个index.js文件
2.vsvode 配置自动编译ts文件
(1)tsc --init 生成一个tsconfig.json文件
(2)修改tsconfig.json中outDir为'./js'
(3)Terminal -> Run Task -> tsc: watch
3.ts中的数据类型
boolean、number、string、array、tuple、enum、any、null、undefined、void、never
1)let flag:boolean=true;
2)let num:number = 456;
3)let str:string = 'wq';
4)定义数组的两种写法
let arr:number[] = [1,2,3]; // 数组中的所有数据类型为number类型
let arr:Array<number> = [1,2,3];
5)元组类型(tuple): 属于数组中的一种,数组中的类型可以很多种
let arr:[number,string] = [1,'wq'];
6)枚举类型
enum Flag{
success=1,
error=0
}
let result:Flag=Flag.success;
说明:如果没有赋值就默认输出下标
enum Color{
white,
black=0,
orange
}
let color:Color[] = [Color.white,Color.black,Color.orange];
console.log('color',color); // [0,0,1]
说明:如果给其中一个赋值为数字,那么后面的未赋值的值就依次增加
7)void 类型:一般用于定义方法的时候没有返回值
function run():void{
console.log('没有任何类型')
}
run();
4.函数
function run():string{
return 'run';
}
1)匿名函数
let fun = function():number{
return 123;
}
2)参数方法
function getInfo(name:string,age:number):object{
return {
name,
age
}
}
3)可选参数
function getInfo(name:string,age?:number):object{
return {
name
}
}
说明:可选参数必须配置到参数的最后面
4)默认参数
function getInfo(name:string,age:number=20):object{
return {
name,
age
}
}
5)剩余参数
function sum(a:number,b:number,...c:number[]):void{
console.log(a,b,c);
}
6)函数重载
function getInfo(name:string):string;
function getInfo(age:number):number;
function getInfo(str:any):any{
if(typeof str === 'string'){
return str;
} else {
return str;
}
}
getInfo(1) // 由于重载,所以只能是string或者是number类型
5.类
1)es5中继承:原型链+构造函数组合继承
对象冒充(call):可以继承属性和方法,但是不能继承其原型链上面的属性和方法
原型链继承(prototype):可以继承属性和方法,也能继承其原型链上面的属性和方法,但是在实例化子类的时候无法传参
例子:
function car(name){
this.name=‘car’;
this.info = ()=>{
console.log(this.name)
}
}
function benci(name){
Car.call(this);
}
benci.prototype = Car.prototype;
2)定义类
class Person{
name:string; // 前面省略了public
constructor(name:string){
this.name = name;
}
getName():string{
return this.name;
}
setName():void{
this.name = name;
}
run():void{
console.log(this.name);
}
}
3)继承
class Web extends Person{
constructor(name:string){
super(name);
}
}
4)类里面的修饰符
public:共有 在类里面、子类、类外面都可以访问
protected:保护类型 在类里面、子类里面可以访问、在外面可以访问
private:私有 只能在类内部访问
5)静态属性 静态方法
class Person{
name:string;
static age: number = 20;
constructor(name:string){
this.name = name;
}
static drink(){
// 注意:静态方法只能调用静态属性
console.log(this.age);
}
}
Person.drink();
6)多态:父类定义一个方法不执行,让继承它的子类去实现,每个子类都表现不同的表现
class Person{
eat(){}
}
class Chinese extends Person{
eat(){
return '吃米饭';
}
}
class Americal extends Person{
eat(){
return '吃牛排';
}
}
7)抽象类与抽象方法:
不包含具体实现必须在派生类中实现;
抽象方法只能放在抽象类中;
子类中必须实现抽象类中的所有抽象方法
abstract class Animal{
eat(){};
abstract drink():void;
}
class Person extends Animal {
drink():void{
}
}
6.接口(定义接口,比抽象类更加严格)
1)属性接口
interface FullName{
firstName: string;
secondName: string;
}
function printName(name:FullName):void{
console.log(name);
}
// 这种情况传参只能是绝对匹配,不能有多余的参数或者少了参数,要想多加参数定义新变量单独出来
printName({firstName:'w',secondName:'q'});
let wq = {
firstName:'w',
secondName:'q',
love:'wq'
}
printName(wq);
可选属性:
interface FullName{
firstName: string;
secondName?: string;
}
2)函数类型接口:对方法传入的参数以及返回值进行约束
interface encrypt{
(key:string,value:string):string;
}
let md5:encrypt=(key:string,value:string):string{
return name+value;
}
3)可索引接口:
①对数组的约束
interface UserArr{
// 下标为number类型,值为string类型
[index:number]:string
}
let arr:UserArr = ['wq'];
②对对象的约束
interface UserObj{
[index:string]:string;
}
let arr:UserObj={name:'20'}
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);
}
}
5)接口扩展:接口可以继承接口
interface Animal{
eat():void;
}
interface Person extends Animal{
work():void;
}
class Chinese implements Person{
public name:string;
constructor(name:string){
this.name = name;
}
eat():void{
}
work():void{
}
}
注意:接口也可以继承接口并且实现类
interface Animal{
eat():void;
}
interface Person extends Animal{
work():void;
}
class Protrammer {
public name:string;
constructor(name:string){
this.name = name;
}
coding(code:string){
}
}
class Chinese extends Protrammer implements Person{
constructor(name:string){
super(name); // 写父类中constructor中的参数
}
eat():void{
}
work():void{
}
}
6)泛型:解决类、接口、方法的复用性,以及对不特定数据结构的支持。在编译期间不确定方法的类型,在方法调用时,由程序员去指定类型
①简单定义
function getData<T>(value:T):T{
return value;
}
console.log(getData<number>(123));
console.log(getData<string>('wq'));
②泛型类
class Fx<T>{
public name:T;
constructor(name:T){
this.name = name;
}
run():T{
return this.name;
}
}
let min = new Fx<string>('wq');
console.log(min.run());
③泛型接口
第一种写法:
interface Congifg{
<T>(name:T):T;
}
let con:Congifg = function<T>(name:T){
return name;
}
console.log(con<string>('123'))
let con2:Congifg = <T>(name:T)=>{
return name;
}
console.log(con2<string>('wq'));
第二种写法:
interface Config<T>{
(name:T,age:number):T;
}
let myCon:Config<string> = (name:string,age:number){
return name;
}
④把类作为参数传入的泛型类
class User{
username:string | undefined;
password:string | undefined;
}
class Mysql<T>{
add(user:T):boolean{
console.log(user);
return true;
}
}
let user = new User();
user.username = 'wq';
user.password = '123456';
let db = new Mysql<User>();
db.add(user);
⑤类实现泛型接口
interface Person<T>{
add(info:T):boolean;
update(info:T):boolean;
}
class Chinese<T> implements Person<T>{
add(info:T):boolean{
return true;
}
update(info:T):boolean{
return true;
}
}
7 装饰器:可以注入到类、方法、属性参数上来扩展类、属性、方法的功能
一、类装饰器
①无参
// 类装饰器
function logClass(params:any){
console.log(params); // 指的是被加装饰器的类
params.prototype.apiUrl='XXX';
params.prototype.run=function(){
console.log('run');
}
}
@logClass
class HttpClient{
constructor(){
}
getData(){
}
}
let http:any = new HttpClient();
console.log(http.apiUrl);
②有参
// 类装饰器
function logClass(params:string){
// params指的是传入的参数,target指的是当前被加装饰器的类
console.log(params);
return function(target:any){
target.prototype.apiUrl = params;
}
}
@logClass('http://www.baidu.com')
class HttpClient{
constructor(){
}
getData(){
}
}
let http:any = new HttpClient();
console.log(http.apiUrl);
③重载构造函数的例子
function logClass(target:any){
// 指的是被加上装饰器的类
console.log(target);
return class extends target{
apiUrl:any = '我是修改后的数据';
getData(){
this.apiUrl += '修改...';
console.log(this.apiUrl);
}
}
}
@logClass
class HttpClient {
public apiUrl: string | undefined;
constructor(){
this.apiUrl = '我是构造函数里面的apiUrl';
}
getData(){
console.log(this.apiUrl);
}
}
let http = new HttpClient();
http.getData();
二、属性装饰器
// 类装饰器
function logClass(params:string){
// params指的是传入的参数,target指的是当前被加装饰器的类
console.log(params);
return function(target:any){
}
}
// 属性装饰器
function logProerty(params:any){
/*
params: 传入的参数
target: 类的原型
attr: 被加上属性装饰器的属性名
*/
return function(target:any,attr:any){
console.log('logProerty',params,target,attr);
target[attr] = params;
}
}
@logClass('http://www.baidu.com')
class HttpClient{
@logProerty('http://www.baidu.com')
public url: any | undefined;
@logProerty('wq')
public name: any | undefined;
constructor(){
}
getData(){
console.log('url',this.url);
}
}
let http:any = new HttpClient();
http.getData();
三、方法装饰器
// 方法装饰器
function logMethod(params:any){
/*
params: 传入的参数
target:对于静态方法来说是类的构造函数,对于实例方法是类的原型对象
methodName: 方法名
desc:成员的属性描述符
*/
return function(target:any,methodName:any,desc:any){
console.log('method',target,methodName,desc,params);
// 修改getData方法,把装饰器方法里面传入的所有参数改为string类型
let oldMethod = desc.value;
// args是传入到改方法中的参数
desc.value = function(...args:any[]){
args = args.map((value)=>{
return String(value);
})
console.log('args',args)
oldMethod.apply(this.args);
}
}
}
class HttpClient{
constructor(){
}
@logMethod('wq')
getData(){
console.log('我是getData里面的方法')
}
// @logMethod('zy')
static getInfo(){
}
}
let http:any = new HttpClient();
http.getData(123,'wq');
四、方法参数装饰器
// 方法参数装饰器
function logParmas(params:any){
/*
params:传入的参数
target:对于静态方法来说是类的构造函数,对于实例方法是类的原型对象
methodName:方法名称
paramsIndex:参数索引
*/
return function(target:any,methodName:any,paramsIndex:any){
console.log('logParmas',params,target,methodName,paramsIndex);
target.apiUrl = params;
}
}
class HttpClient{
constructor(){
}
getData(@logParmas('uuid') uuid:any){
console.log('我是getData里面的方法',uuid)
}
}
let http:any = new HttpClient();
http.getData(123456);
注意:装饰器执行顺序:
属性装饰器->方法装饰器->类装饰器
对于同一种装饰器,从右到左,从下到上