zoukankan      html  css  js  c++  java
  • typescript

    一、介绍

    1.typescript是由微软开发的一款开源的编程语言

    2.ts是js的超级,拓展了js语法,更像java/c#这样面向对象语言,更适合开发大型项目。

    3.谷歌也在大力支持ts,谷歌的angular2x+ 就是基于ts语法的。

    4.最新的Vue ,React 也可以集成ts。

    二、安装和编译

    1.安装:npm install -g typescript

    2.生成配置文件:tsc --init  创建tsconfig.json 文件(eg:可修改输出地址“outDir”:“./js”,等配置)

    3.编译:tsc hello.ts  (hello.ts 是自己建的ts名)

    4.点击菜单栏 任务-运行任务  点击tsc 监视-tsconfig.json ,然后就可以自动生成代码了。

    三、ts的数据类型

    1.布尔类型(boolean)

    2.数字类型(number)

    3.字符串类型(string)

    4.数组类型(array)

    5.元祖类型(tuple)

    6.枚举类型(enum)

    7.任意类型(any)

    8.null 和 undfined

    9.void 类型

    10.never类型

    四、各类型的用法

    1.布尔类型(boolean)

    let flag:boolean = true;
    flag =false;

    2.数字类型(number)

    let num:number;
    num =3;

    3.字符串类型(string)

    let str:string = '';
    str = 'I am string';

    4.数组类型(array)

    let arr:string[]=[];
    arr = ['1','2','3','4'];
    or
    let arr:Array<number> =[1,2,3,4];

    5.元祖类型(tuple)

    //已知数组元素的个数,并且知道每个元素的类型
    let tupleArr :[string,number] =['lalala',2];

    6.枚举类型(enum)

    enum Color{
        red = 1,
        blue,
        orange = 5,
        green = 7
    }
    let redNum:Color = Color.red   //1
    let blueNum:Color = Color.blue    //2
    let orangeNum:Color = Color.orange    //5
    
    let red:string = Color[1]   //red
    let blue:string = Color[2]    //blue
    let orange:string = Color[5]    //orange

    7.任意类型(any)

    let notSure:any = 4; 
    notSure = 'maybe a string instead';
    notSure = false; //okay

    8.null 和 undfined

        //strictNullChecks标记的启用是在tsconfig.json文件里进行配置。
    // {
    //     "compilerOptions": { //编译选项,可以被忽略,这时编译器会使用默认值
    //         "strictNullChecks": false, //在严格的null检查模式下,null和undefined值不包含在任何类型里,只允许赋值给void和本身对应的类型。
    //     }
    // }
    //"strictNullChecks": false,
    //默认情况下,null 和 undefined 是其它类型的子类型,可以赋值给其它类型,如number类型,此时,赋值后的类型会变成 null 或 undefined。
    let hh: number;
    hh = null; //ok的
    hh = undefined;  //ok的
    
    //"strictNullChecks": true,
    let ss: number;
    ss = null; //提示不可以
    ss = undefined;  //提示不可以

    //定义没有赋值就是undifined;
    let aa :string | undifined;
    console.log(aa) //undefined

    //一个元素可能是number,null,undifined
    let num: number | null | undefined
    num=123;

    9.void 类型

    //表示方法没有返回任何类型
    function run(): void {
        console.log(111);
    
    }
    run()
    //表示传参是number类型,函数返回值也是number类型
    function sum(num:number): number {
        console.log(111);
        return num + 123
    }
    sum(12);

    10.never类型

    //never类型是任何类型的子类型,也可以赋值给任何类型;然而,没有类型是never的子类型或可以赋值给never类型(除了never本身之外)。
    // 即使 any也不可以赋值给never。通常表现为抛出异常或无法执行到终止点(例如无线循环)。比如:
    let x: never; let y: number; // 运行错误,数字类型不能转为 never 类型 x = 123; // 运行正确,never 类型可以赋值给 never类型 x = (() => { throw new Error('exception') })(); // 运行正确,never 类型可以赋值给 数字类型 y = (() => { throw new Error('exception') })(); // 返回值为 never 的函数可以是抛出异常的情况 function error(message: string): never { throw new Error(message); } // 返回值为 never 的函数可以是无限循环这种无法被执行到的终止点的情况 function loop(): never { while (true) { } }

    五、类

    1.类的写法

    2.类的继承

    3.属性修饰符(public、protected、private)

    4.必传参数和可选参数

    //类里面的修饰符:ts里定义属性的时候提供了三种修饰符:
    /*
    public:共有   在类里面、子类、类外面都可以访问
    protected:保护类型   在类里面,子类里面可以访问,在类外部没法访问
    private:私有     在类里面可以访问 ,类外面和子类都不访问
    属性如果不加修饰符,默认是public
    */
    class Person {
        name: string; //必传,属性修饰符这里没写就默认是public,同public name:string;
        private sex: string;
        protected age?: number; //age:可有可没有
    
        //namepro:必传,agepro:可传可不传,可选参数必须配置到 参数的最后面 //‘lisi’是namepro的默认值
        constructor(namepro: string = 'lisi', sexpro: string = '男', agepro?: number) {
            this.name = namepro;
            this.age = agepro;
            this.sex = sexpro;
        }
        run(): void {
            console.log(this.name);
        }
    }
    let zhangsan = new Person('zhangsan', '女');
    zhangsan.run();
    zhangsan.age;  //提示出错。age是保护类型
    
    class Web extends Person {
        constructor(name: string) {
            super(name) //继承父级的参数需要同过super函数传值
        }
        work() {
            console.log(this.sex); //sex是父类的私有属性,所以子类是访问不到的,这里会提示错误
    
        }
    }

    5.参数中的三点运算符

    //三点运算符,接受新参传过来的值
    function sumFn(...result: number[]): number {
        let sum: number = 0;
        for (let i = 0; i < result.length; i++) {
            sum += result[i];
        }
        return sum;
    }
    sumFn(1, 2, 3, 4);
    sumFn(1, 2, 3, 4, 5, 6)
    //如果有默认的参数,那传参前面就是默认的参数,剩下的就在。。。的result中
    function sumFn(a:number,b:number,...result: number[]): number {
        let sum: number = a+b;
        for (let i = 0; i < result.length; i++) {
            sum += result[i];
        }
        return sum;
    }
    sumFn(1, 2, 3, 4);
    sumFn(1, 2, 3, 4, 5, 6)

    六、ts函数重载

    1.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;
        }
    }
    getInfo('张三')  //我叫张三
    getInfo(20)  //我的年龄20

    七、类的静态属性 静态方法

    1. /*es5中的写法*/ 
    function
    Person () {   // this.run = function () {} // 实例方法   // this.run = ()=> {} } Person.run = function () {} // 静态方法
    2./*es6的写法*/
    class Person1 {   name:string;   static sex = 'man'; // 静态属性   constructor(name: string) {     this.name = name;   }     eat() {     console.log(`${this.name}吃饭`)   }   static work() {   console.log(`这是一个静态方法` + Person1.sex)   // console.log(`${this.name}哈哈`) // 错误的写法,静态方法里面无法调用类的属性、方法。   } } var p = new Person1('aaa'); p.eat(); // 实例方法调用 Person1.work(); // 静态方法调用

    八、ts中的抽象类和抽象方法,多态

    1.typescript中的抽象类是提供其它类的基类,不能直接被实例化;

    2.用abstract关键字定义的抽象方法和抽象类,不包括具体实现必须在派生类实现。

    3. 抽象类: abstract 修饰, 里面可以没有抽象方法。但有抽象方法(abstract method)的类必须声明为抽象类(abstract class)

    4.抽象类用于定义标准

    5. 多态:父类定义一个方法不去实现,让继承它的子类去实现  每一个子类有不同的表现

    abstract class Animal {
        name: string;
        constructor(name: string) {
            this.name = name;
        }
        //抽象方法 ,不包含具体实现,要求子类中必须实现此方法
        abstract eat(): any;
        //非抽象方法,无需要求子类实现、重写
        run(): void {
            console.log('非抽象方法,不一定要子类实现、重写');
        }
    }
    //子类中必须实现父类抽象方法,否则ts编译报错
    class Dog extends Animal {
        eat() {
            return this.name + '吃鱼'
        }
    }
    class Cat extends Animal {
        //子类中必须实现父类抽象方法,否则ts编译报错
        eat() {
            return this.name + "吃鱼";
        }
    }
    var dog = new Dog("tom");
    var cat = new Cat("kitty");
    console.log(dog.eat());
    console.log(cat.eat());
    
    //多态 ,一种事物的不同表现形态。如下面的代码中 先声明变量f是Animal类型,具体是Dog还是Cat,在new 对象时才知道
    //如果是Dog,则f.eat()调用的是Dog类中的eat方法;如果是Cat,则f.eat()调用的是Cat类中的eat方法,这就是多态!!!
    var f: Animal;//声明变量为Animal类型
    //f=new Dog("sunny");
    f = new Cat("sunny");
    console.log(f.eat());

    九、接口

    1.接口:行为和动作的规范,对批量方法进行约束

    2.接口的作用:在面向对象的编程中,接口是一种规范的定义,它定义了行为和动作的规范,在程序设计里面

    3.分类:属性接口、函数类型接口、可索引接口、类类型接口

    (1)属性接口:

    //属性接口
    interface fullName{
        firstName:string;
        secondName:string;
    }
    function getName(name:fullName):void{
        console.log(name.firstName + name.secondName); 
    }
    getName({
        firstName:'Li',
        secondName:'haha'
    })
    interface Shape {
        head: string;
        arm: string;
    }
    interface Human {
        name: string;
        age: number;
        shape: Shape;
        say(word: string): void;
    }
    
    let jack: Human = {
        name: 'Jack',
        age: 18,
        shape: {
            head: 'head',
            arm: 'arm'
        },
        say(word: string) {
            console.log(word)
        }
    }
    jack.say('hi')

    (2)函数类型接口:

    //函数类型接口
    interface Fn{
        (key:string,val:string):string;
    }
    let add1:Fn = function(key:string,val:string):string{
        return key+val;
    }
    let add2:Fn = function(key:string,val:string){
        return `${key}------${val}`
    }

    (3)可索引接口(数组对象的约束,不常用)

    //ts定义数组的方式
    let arr1: number[] = [11, 22];
    let arr2: Array<string> = ['11', '22'];
    //可索引接口的实现
    interface UserArr {
        [index: number]: string
    }
    let arr3: UserArr = ['aa', 'bb'] //ok
    console.log(arr3[0]);
    let arr4:UserArr=[11,'aa'];//报错
    
    interface UserObj{
        [index:string]:string
    }
    let arr5:UserObj ={name:'张三'} //OK,但是这样实现已经不是数组,没有意义了,所以不常用

    (4)类类型接口(对类的约束,和抽象类有点像)

    interface Aniaml1 {
        name: string;
        eat(str: string): void;
    }
    //implements ,是对类Aniaml1的实现
    class Dog1 implements Aniaml1 {
        name: string;
        constructor(name: string) {
            this.name = name;
        }
        eat(str: string) {
            console.log(this.name + '吃粮食' + str);
    
        }
    }
    let d = new Dog1('小黑');
    d.eat('肉');

    4.接口的拓展:接口可以继承接口

    interface Animal {
        eat(): void;
    }
    interface Person extends Animal {
        work(): void;
    }
    class Web implements Person {
        name: string;
        constructor(name: string) {
            this.name = name;
        }
        eat() {
            console.log(this.name + '喜欢吃馒头');
        }
        work() {
            console.log(this.name + '写代码');
        }
    }
    let zhangsan = new Web('zhangsan');
    zhangsan.work();

    十、泛型

    1.泛型的定义:指在定义函数、接口或者类的时候, 不预先指定其类型,而是在使用时手动指定其类型的一种特性

    2.泛型分类:泛型函数、泛型类、泛型接口

    (1)泛型函数

    //使用泛型函数(T:类型变量)
    function myfn<T>(args: T): T {
        return args;
    }
    let output = myfn<string>("Hello"); //明确传入类型参数
    let output2 = myfn("Hello")  //不传入类型参数,TS根据上下文自动推断类型
    //使用泛型变量(这可以让我们把泛型变量T当做类型的一部分使用,而不是整个类型)
    function myfn1<T>(args: T[]): T[] {
        console.log(args.length)
        return args;
    }
    function myfn2<T>(args: Array<T>): Array<T> {
        console.log(args.length);
        return args;
    }

    (2)泛型类

    class add<T>{
        value: T;
        add: (x: T, y: T) => T;
    }
    let myTest = new add<number>();
    myTest.value = 0;
    myTest.add = function (x, y) {
        return x + y
    }

    (3)泛型接口

    //第一种方法
    interface Test {
        <T>(args: T): T
    }
    let myTest: Test = function <T>(args: T): T {
        return args;
    }
    myTest<string>('20');
    myTest<string>(20);
    
    //第二种方法
    interface Test1<T> {
        (args: T): T 
    }
    function myfn1<T>(args: T): T { 
        return args;
    }
    let myTest1: Test1<string> = myfn1;
    myTest1('20') //ok
    myTest1(20)//报错

    (4)泛型约束(类型变量继承接口)

    //例中,传入的参数必须具有length属性
    interface Test{
        length:number;
    }
    function myfn<T extends Test>(args:T):T{
        console.log(args.length)
        return args;
    }
    myfn(3); //error
    myfn("abc") //3

    十一:模块

    1.模块的概念

    2.模块导出的几种方式:export导出声明、export导出语句、export default、import 导入模块

    3.模块封装(DB库)

    4.命名空间

    十二、装饰器

    1.概念

    2.分类:属性装饰器、方法装饰器、方法参数装饰器、类装饰器(装饰器的执行顺序也是这样)

    3.装饰器的写法:普通装饰器(无法传参)、装饰器工厂(可传参)

    (1)普通装饰器

    //类装饰器
    function logClass(target: any) {
        console.log(target); //httpClient类
        params.prototype.apiUrl = '动态扩展的属性';
        params.prototype.run = function () {
            console.log('动态拓展的方法');
        }
    }
    
    @logClass  
    class httpClient {
        constructor() {
    
        }
        getData() {
    
        }
    }
    let http: any = new httpClient();
    //类装饰器重载构造函数和当前类的方法(普通装饰器)
    function logClass(target: any) { //target:httpClient 类
        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: any = new httpClient();
    console.log(http.apiUrl);  //我是修改后的数据

    (2)装饰器工厂(可传参)

         2.1   类装饰器

    //类装饰器(装饰器工厂的方式)
    function logClass(params: any) {  //params:传的参数
    
        return function (target: any) {//target:httpClient类
            console.log(params);//hello
            console.log(target);//httpClient类
    
            target.prototype.apiUrl = params; //可以用上传的参数
            target.prototype.run = function () {
                console.log('动态拓展的方法');
            }
        }
    }
    
    @logClass('hello')   //可以传参
    class httpClient {
        constructor() {
    
        }
        getData() {
    
        }
    }
    let http: any = new httpClient();
    console.log(http.apiUrl);  //hello

      2.2  属性装饰器

    //属性装饰器
    function logProperty(params: any) { //params:传的值:我是属性装饰器
        return function (target: any, attr: any) { //target:httpClient 类,attr:apiUrl
            target[attr] = params;
        }
    }
    class httpClient {
        @logProperty('我是属性装饰器')    //注意后面是不能加分号的
        public apiUrl: string | undefined;
        constructor() {
            this.apiUrl = '我是构造函数里面的apiUrl';
        }
        getData() {
            console.log(this.apiUrl);
        }
    }
    let http: any = new httpClient();
    console.log(http.apiUrl);  //我是属性装饰器

    2.3 方法装饰器//方法装饰器

    function get(params: any) { //params:传的值:我是方法装饰器
        //target:httpClient类,methodName:方法名getData, desc:方法的描述
        return function (target: any, methodName: any, desc: any) {
            target.addPara = '我是拓展的属性';  //同类装饰器的方法
            target.addFn = function () {       //同类装饰器的方法 
                console.log('我是拓展的方法');
            }
            //修改装饰器的方法,把装饰器里面传入的参数改为string类型 
            //获取当前的方法 desc.value =getData() {console.log(this.apiUrl);}
            //先保存当前的方法
            let oldMethond = desc.value;
            //修改当前的方法
            desc.value = function (...args: any[]) {
                args = args.map((val) => {
                    return String(val)
                })
                console.log(args);//['123','xxx'] 
           console.log(params); //我是方法装饰器
    //将原来的方法继承到修改后的方法里面,这样既有修改的方法,又包含原有未修改的方法 oldMethond.apply(this, args) } } } class httpClient { public apiUrl: string | undefined; constructor() { this.apiUrl = '我是构造函数里面的apiUrl'; } @get('我是方法装饰器') getData(...args: any[]) { console.log(args); //['123','xxx'] console.log(this.apiUrl); //我是构造函数里面的apiUrl } } let http: any = new httpClient(); http.getData; //['123','xxx']
    //我是方法装饰器
    //['123','xxx'] //我是构造函数里面的apiUrl

    2.4 方法参数装饰器

    //方法参数装饰器:可以为类的原型增加一些元素数据(一般不用,类装饰器就可以做到这些)
    function logParams(params: any) { //params:传的值:我是方法参数装饰器
        //target:httpClient类,methodName:方法名getData, paramsIndex:函数参数的index索引
        return function (target: any, methodName: any, paramsIndex: any) {
            target.addUrl = 'params';//可以为类的原型增加一些元素数据
        }
    }
    class httpClient {
        public apiUrl: string | undefined;
        constructor() {
        }
       
        getData( @logParams('我是方法参数装饰器') uuid:any) {
            console.log(uuid); //haha
        }
    }
    let http: any = new httpClient();
    http.getData('haha');
  • 相关阅读:
    统一建模语言UML轻松入门之综合实例
    统一建模语言UML轻松入门之动态建模
    LINQ体验(3)——C# 3.0新语言特性和改进(下篇) 【转】
    Visual Studio 2008新特性【转】
    vs2008 新特性【转】
    LINQ体验(1)——C# 3.0新语言特性和改进(上篇) 【转】
    C# 3.0 的Lambda表达式(Lambda Expressions)【转】
    LINQ体验(2)——C# 3.0新语言特性和改进(上篇) 【转】
    结构体计算结构体字节大小以及字节对齐
    web.config 中SessionState的配置
  • 原文地址:https://www.cnblogs.com/zhengyulu/p/12077981.html
Copyright © 2011-2022 走看看