您的位置:首页 > Web前端 > JavaScript

TypeScript与JavaScript不同之处系列(二) ===> 接口

2020-04-05 07:16 549 查看

本系列目的: 列出TypeScript与JavaScript的不同点, 缩小文档内容, 提高学习速度. 原文档地址: https://www.tslang.cn/index.html

全系列目录

文章目录

  • 1.3. 只读属性
  • 2. 可索引类型
  • 3. 函数
  • 4. 类类型
  • 1. 对象

    1.1. 最简单的使用例子

    interface LabelledValue {
    label: string;
    }
    
    function printLabel(labelledObj: LabelledValue) {
    console.log(labelledObj.label);
    }
    
    let myObj = {size: 10, label: "Size 10 Object"};
    printLabel(myObj);

    1.2. 可选属性

    带有可选属性的接口与普通的接口定义差不多,只是在可选属性名字定义的后面加一个?符号

    需要注意的是, 即使是可选属性也要遵循基本原则, 如下面这个例子, 如果传入的参数属性不在SquareConfig中的话也会报错

    interface SquareConfig {
    color?: string;
    width?: number;
    }
    
    function createSquare(config: SquareConfig): {color: string; area: number} {
    let newSquare = {color: "white", area: 100};
    if (config.color) {
    newSquare.color = config.color;
    }
    if (config.width) {
    newSquare.area = config.width * config.width;
    }
    return newSquare;
    }
    
    let mySquare = createSquare({color: "black"});
    let myError = createSquare({color: "black", gkd: '1'}); // 报错

    1.2.1. 额外检查

    上面例子可以看到如果, 传入

    gkd
    属性就会报错, 那么如何绕开这些错误呢.

    // 1. 使用类型断言(类型断言参见下面的介绍)
    let mySquare = createSquare({ width: 100, gkd: '1'} as SquareConfig);
    
    // 2. 增加检验属性
    interface SquareConfig {
    color?: string;
    width?: number;
    [propName: string]: any;
    }

    官方建议, 在这里,如果支持传入gkd属性到createSquare,你应该修改SquareConfig定义来体现出这一点。

    1.2.1.1. 类型断言

    通过类型断言这种方式可以告诉编译器,“相信我,我知道自己在干什么”。 类型断言好比其它语言里的类型转换,但是不进行特殊的数据检查和解构。 它没有运行时的影响,只是在编译阶段起作用。

    TypeScript
    会假设你,程序员,已经进行了必须的检查。

    类型断言有两种形式。 其一是“尖括号”语法:

    let someValue: any = "this is a string";
    let strLength: number = (<string>someValue).length;
    
    // 另一个为as语法:
    
    let someValue: any = "this is a string";
    let strLength: number = (someValue as string).length;

    两种形式是等价的。 至于使用哪个大多数情况下是凭个人喜好;然而,当你在

    TypeScript
    里使用JSX时,只有 as语法断言是被允许的

    1.3. 只读属性

    一些对象属性只能在对象刚刚创建的时候修改其值。 你可以在属性名前用

    readonly
    来指定只读属性:

    interface Point {
    readonly x: number;
    readonly y: number;
    }
    
    let p1: Point = { x: 10, y: 20 };
    p1.x = 5; // error!, 因为Point只读

    TypeScript具有

    ReadonlyArray<T>
    类型,它与
    Array<T>
    相似,只是把所有可变方法去掉了,因此可以确保数组创建后再也不能被修改:

    let a: number[] = [1, 2, 3, 4];
    let ro: ReadonlyArray<number> = a;
    ro[0] = 12; // error!
    ro.push(5); // error!
    ro.length = 100; // error!
    a = ro; // error!
    
    // 可以用类型断言重写:
    a = ro as number[];

    2. 可索引类型

    它描述了对象索引的类型,还有相应的索引返回值类型, 例:

    interface StringArray {
    [index: string]: number;
    length: number;    // 可以,length是number类型
    name: string;       // 错误,`name`的类型与索引类型返回值的类型不匹配
    }
    
    let myArray: StringArray;
    myArray['gkd'] = 123;
    
    let myStr: number = myArray['gkd'];

    3. 函数

    为了使用接口表示函数类型,我们需要给接口定义一个调用签名。 它就像是一个只有参数列表和返回值类型的函数定义。参数列表里的每个参数都需要名字和类型

    interface SearchFunc {
    (source: string, subString: string): boolean;
    }
    
    //对于函数类型的类型检查来说,函数的参数名不需要与接口里定义的名字相匹配。
    
    let mySearch: SearchFunc;
    mySearch = function(src: string, sub: string): boolean {
    let result = src.search(sub);
    return result > -1;
    }
    
    //  如果你不想指定类型也可以这么写
    let mySearch: SearchFunc;
    mySearch = function(src, sub) {
    let result = src.search(sub);
    return result > -1;
    }

    4. 类类型

    类类型按照js话来讲, 就是对象.

    4.1. 简单使用

    // 例1
    
    interface ClockInterface {
    currentTime: Date;
    setTime(d: Date);
    }
    
    class Clock implements ClockInterface {
    currentTime: Date;
    setTime(d: Date) {
    this.currentTime = d;
    }
    constructor(h: number, m: number) { }
    }

    4.2. 继承

    interface Shape {
    color: string;
    }
    
    interface PenStroke {
    penWidth: number;
    }
    
    interface Square extends Shape, PenStroke {
    sideLength: number;
    }
    
    let square = <Square>{}; // 可以理解为Square类型的对象
    square.color = "blue";
    square.sideLength = 10;
    square.penWidth = 5.0;
    
    square.gkd= 5.0; // 报错 Property 'gkd' does not exist on type 'Square'.

    4.3. 混合类型

    为JavaScript其动态灵活的特点,有时你会希望一个对象可以同时具有上面提到的多种类型。一个例子就是,一个对象可以同时做为函数和对象使用,并带有额外的属性.

    interface Counter {
    (start: number): string;
    interval: number;
    reset(): void;
    }
    
    function getCounter(): Counter {
    let counter = <Counter>function (start: number) { };
    counter.interval = 123;
    counter.reset = function () { };
    return counter;
    }
    
    let c = getCounter();
    c(10);
    c.reset();
    c.interval = 5.0;

    4.4. 接口继承类

    当接口继承了一个类类型时,它会继承类的成员但不包括其实现。 就好像接口声明了所有类中存在的成员,但并没有提供具体实现一样。 接口同样会继承到类的private和protected成员

    class Control {
    private state: any;
    }
    
    interface SelectableControl extends Control {
    select(): void;
    }
    
    class Button extends Control implements SelectableControl {
    select() { }
    }
    • 点赞
    • 收藏
    • 分享
    • 文章举报
    刘翾 博客专家 发布了167 篇原创文章 · 获赞 275 · 访问量 59万+ 他的留言板 关注
    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: 
    相关文章推荐