typescript就这回事

Posted 叶家伟的博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了typescript就这回事相关的知识,希望对你有一定的参考价值。

本文讲解typescript语法

由于js语法本身的混乱,再加上目前框架的割据,导致typescript用起来没有一致性,本文尽量总结实际开发中可能会用到的知识点

目录

数据类型
类型断言
duck typing
函数类型的验证
索引验证
类验证
接口扩展
泛型
与第三方库一起使用
命名空间
react组件属性验证


  1. 数据类型

    Boolean 布尔类型 let isDone: boolean = false;
    Number 数字类型 let num: number = 5;
    String 字符串类型 let str: string = ‘aa‘;
    Array 数组 
        let list: number[] = [1, 2, 3];
        let list: Array<nubmber> = [1, 2, 3];
        let list: [string, number] = [‘aa‘, 11];
        let arr: ReadonlyArray<number> = [1, 2, 3]; // 只读数组
    Enum 枚举类型,是typescript对javascript语法的扩展类型
        枚举类型用来将一组无意义的数值转变成识别度高的属性
        enum Color {Red, Green, Blue} // 声明枚举
        let a: Color = Color.Grean // 1
        let a: string = Color[2]; // Blue
        枚举值,默认从0开始递增,可以手动赋值
    Any 类型,是typescript自己扩展的类型
        any类型的作用就是用来暂时关闭类型验证,对此变量不做任何类型的验证,我不推荐用这个类型,建议Object代替
        let a: any = 1; 
    Object 类型,是typescript自己扩展的类型
        Object类型的作用,是表示此变量可以为任意类型的值
        let a: Object = 1;
    Void 类型,是typescript自己扩展的类型
        Void 类型,主要用来表示没有返回值的函数
        function a(): void {}
    Null 和 Undefined 类型
        顾名思义,表示一个变量专门用来表示 Null 或者 Undefined
        let a: undefined = undefined;
        let a: null = null;
    Never 类型
        用来表示报错的函数,或者死循环的函数
        function fn() :never { throw new Error("aaa"); }
        function fn (): never { while(true) {} }
  2. 类型断言

    字面意思‘断言’,即人为决定类型,不需要typescript自动侦测
    两种语法
        尖括号语法,不推荐,此法react不支持
            let str: Object = "aaa";
            let strLength: number = (<string>someValue).length;
        as语法,推荐此语法,并且c#内部也推荐此语法
            let str: Object = 111;
            let num: Number = str as Number;
  3. duck typing

    duck typing是任何一门面相对象语言都有的类型验证方式,说简单点,就是一次验证多个变量
    宽松的duck typing,只要变量需要验证的参数存在于传递的参数里面即可
        对象写法
            function fn(obj: {a: string}) {}
            let obj = {a: "aa", b: 1};
            fn(obj);
        interface写法
            interface params {
                a: string
            }
            function fn(obj: params) {}
            let obj = {a: "aa", b: 1};
            fn(obj);
        可选的参数
            对象写法 
                function fn(obj: {a?: string}) {}
            interface写法  
                interface params {
                    a?: string
                }
                function fn(obj: params) {}
        只读的参数
            对象写法
                {readonly a: string}
            interface写法
                interface params {
                    readonly a: string
                }
    严格的duck typing,传递的参数和验证的参数必须完全一致
        interface params {
            a: string
        }
        function fn(obj: params) {}
        fn({a: "aa"});
        这种模式下可选参数已经失去了意义,为了挽救可选参数,解决方法有如下两种
            as语法
                interface params {
                    a?: string,
                    b?: number
                }
                function fn (obj: params): void {}
                fn({b: 11, c: "bb"} as params);
            索引签名 
                interface params {
                    a?: string,
                    b?: number,
                    [propName: string]: any
                }
                function fn (obj: params): void {}
                fn({b: 11, c: "bb", d: true});  
  4. 函数类型的验证

    函数的验证使用接口来实现会更加的简洁
    interface myFn {
        (a: string, b: number): void
    }
    let fn: myFn = function(name, age){};
    fn("aa", 11);
    在定义函数时,函数的参数可以写类型也可以不写,并且参数的名称和接口的参数名称不需要相同
    注意:在javascript中,函数其实就是一个对象,所以函数的验证可以存在即是对象又是函数的情况,如下
        interface Test {
            (a: string): string;
            b: number;
        }
        function Fn() : Test {
            let fn = function(a: string){return a} as Test;
            fn.b = 111;
            return fn;
        }
    函数验证的其他写法
        let fn: (a: number) => void = function(x: number): void { }
        let fn = function(x: number): void { }
        let fn: (a: number) => void = function(x){ }
        let fn: (a?: number) => void = function(x){ } 可选参数
        function fn(a: string | number){ } 多种参数类型
  5. 索引验证

    只要可以通过索引访问成员的数据类型,在typescript中都可以使用索引验证
    众所周知,索引可以是字符串和数值,但是在js中,数值的索引等价于字符串的索引,
    也就是说在typescript中,将索引指定为数值类型等价于字符串类型
    interface Entries {
        [index: number]: number;
    }
    let arr: Entries = [1, 2, 3];
    同样还支持只读的索引
        interface ReadonlyStringArray {
            readonly [index: number]: string;
        }
  6. 类验证

    用接口验证类只能验证类的实例属性,构造函数这类的非实例属性无法验证
    interface Test {
        a: string;
        fn(b: number): void;
    }
    class Demo extends React.Component implements Test  {
        a: "aa"
        fn = (b: number) => { }
    }
    typescript对es6的类做了进一步的扩展,使其支持访问修饰符,抽象类抽象方法
        访问修饰符
            Public 默认,公开成员
            private 只能在类内部访问
            protected 本类内部和子类内部可以使用
            Readonly 只读属性
            static 静态属性 
        抽象类,作用和接口类似,主要用来给其他类提供公共成员
            抽象类无法实例化,抽象方法只能提供定义,在子类中必须实现
            abstract class Demo {
                a: string;
                fn():void { console.log("aa"); }
                constructor(a: string) {this.a = a};
                abstract Fn(): void;
            }
            class Test extends Demo {
                constructor(){
                    super("aaaaaa");
                }
                Fn():void {
                    console.log("bbb");
                }
            }
  7. 接口扩展

    接口可以继承其他接口
        interface Test1 {
            a: string;
        }
        interface Test2 {
            b: string;
        }
        interface Test3 extends Test1, Test2 { }
    接口继承其他类
        class Demo {
            public a: string;
            private b: number;
            protected c: string;
        }
        interface Test extends Demo {}
        class Demo1 extends Demo implements Test{
            public a: "aa";
        }
        注意,由于接口继承类,接口可以继承类的private和protected成员,所以子类继承此接口要同时继承父类才行
  8. 泛型

    泛型也是一个非常简单的东西,就是类型参数
        泛型函数
            function fn<T>(params: T): T {
                return params;
            }
            fn<string>(‘aa‘); 显示调用
            fn(‘aa‘); 隐式调用
            完整写法
                let fn: <T>(params: T) => T = function<T>(params: T): T {
                    return params;
                };
        泛型接口
            不提取参数
                interface Itf {
                    <T>(params: T): T;
                }
                let fn: Itf = function<T>(params: T): T {
                    return params;
                };
            提取参数
                interface Itf<T> {
                    <T>(params: T): T;
                }
                let fn: Itf<string> = function<T>(params: T): T {
                    return params;
                };
        泛型类
            class Demo<T>{
                fn: (a: T) => T;
            }
    泛型约束
        没有泛型约束,泛型将毫无用处,泛型参数默认是个白板儿,啥都没有
        一般写法
            interface Demo {
                length: number;
            }
            function fn<T extends Demo>(str: T): T {
                window.console.log(str.length);
                return str;
            }
            fn(‘aa‘);
        相互约束
            function fn<T, K extends keyof T>(obj: T, key: K) {
                window.console.log(obj[key]);
                return obj[key];
            }
            fn({a: 1}, ‘a‘);
        验证类的构造函数
            class Test {
                constructor(){}
            }
            function fn<T>(obj: {new(): T}): T{
                return new obj();
            }
            fn(Test);
  9. 与第三方库一起使用

    很多基于npm的第三方包,都没有使用typescript,那么在ts中想使用这些安装包,需要遵从如下操作
    第一,在项目中新建一个.d.ts文件,如 third.d.ts 
    第二,在文件中定义模块,如
        declare module "url" { // 此模块名必须和第三方包的名字一样
            export interface Url {
                protocol?: string;
                hostname?: string;
                pathname?: string;
            }
            export function parse(urlStr: string, parseQueryString?, slashesDenoteHost?): Url;
        }
        declare module "path" {
            export function normalize(p: string): string;
            export function join(...paths: any[]): string;
            export var sep: string;
        }
        declare module "hot-new-module"; 不想写声明可以不写
    第三,在需要使用第三方包的文件中导入模块
        /// <reference path="third.d.ts"/> 导入.d.ts声明文件
        import * as URL from "url"; 导入模块
        let myUrl = URL.parse("http://www.typescriptlang.org");
  10. 命名空间

    命名空间和js的对象一样,单纯的为了避免命名冲突
    namespace Demo {
        export let a = ‘aa‘;
    }
    window.console.log(Demo.a);
  11. react组件属性验证

    使用React typings注入
        interface Props {
            a: string;
        }
        class App extends React.Component<Props, {}> {
            render() {
                return (
                <div className="App">
                    {this.props.a}
                </div>
                );
            }
        }
    使用此组件
        <App a="aa"/>

以上是关于typescript就这回事的主要内容,如果未能解决你的问题,请参考以下文章

❤ 就这?TypeScript其实并不难!(建议收藏)❤

进大厂也就这回事,工作后2到3年进大厂操作指南

typescript Angular 2测试片段。代码库https://developers.livechatinc.com/blog/category/programming/angular-2/

typescript Angular最终版本的Angular 2测试片段。代码库https://developers.livechatinc.com/blog/category/programming

typescript Angular最终版本的Angular 2测试片段。代码库https://developers.livechatinc.com/blog/category/programming

typescript Angular最终版本的Angular 2测试片段。代码库https://developers.livechatinc.com/blog/category/programming