TypeScript 学习笔记5:Custom Types

原文链接:https://leanpub.com/essentialtypescript/read#leanpub-auto-custom-types

1. 使用interface定义新的类型

1.1. 定义interface

interface Todo {
    name: string;
    completed: boolean;
}

1.2. 使用interface

var todo: Todo = {
    name: "Pick up drycleaning",
    completed: false
};

1.3. 遵守interface 协议

var t1: Todo = {};

var t2: Todo = {
    name: "Pick up drycleaning"
};

这两个变量定义不合法,编译器会报错。因为,它们没有遵守 interface Todo 规定的协议,属性不完整。

1.4. 强制类型转换

var t1 = <Todo>{};

这种写法告诉编译器 t1 符合 Todo 接口。虽然它不符合,但编译器不会报错。

1.5. optional 属性

interface Todo {
    name: string;
    completed?: boolean;
}

var t2: Todo = {
    name: "Pick up drycleaning"
};

completed 后面有个问号,指明:

  1. completed 属性可有可无;

  2. 如果有这个属性,必须是boolean类型。

所以,t2 没有completed属性,但它是符合 Todo 接口的。

1.6. 在接口中定义function

interface ITodoService {
    add(todo: Todo): Todo;
    delete(todoId: number): void;
    getAll(): Todo[];
    getById(todoId: number): Todo;
}

注意,函数名前面不用写 function 。

2. 使用interface描述function

2.1. 定义函数 interface 

function 本身就是Object,函数体是它的一个属性,当然,它也可以有其他的属性。

interface jQuery {
    (selector: string): HTMLElement;
    version: number;
}
说明:

  1. 这个interface定义一个function接口,它模拟了 jQuery(selector) 这个函数。

  2. 注意第二行,定义了一个没有名字的函数,括号中是参数声明,后面是返回值类型。没想通为什么要这么写,先背下来,反正就得这么写。

  3. 第三行定义了一个属性 —— version。

2.2. 使用函数interface


说明:

  1. 上图中,第七行定义了一个函数,函数名是 $,它遵从 jQuery 接口。

  2. 第11行使用刚刚定义的 $ 函数,获取 id="container" 的DOM element。

  3. 第12行,此时,TypeScript 可以推断出element的类型。

3. 给已有的interface添加属性

下面的代码模拟了 jQuery 的 data() 方法:

interface jQueryElement {
    data(name: string): any;
    data(name: string, data: any): jQueryElement;
}

interface jQuery {
    (selector: (string | any)): jQueryElement;
    fn: any;
    version: number;
}

var $ = <jQuery>function(selector) {
    // Find DOM element
};

var todo = { name: "Pick up drycleaning" };
var element = $('#my-element');
element.data('todo', todo);
var savedTodo = element.data('todo');
第8行,fn:any ,这是jQuery提供的一种plugin模式。

如果我们加上如下代码,会给 jQueryElement 添加 todo() 方法:

$.fn.todo = function(todo?: Todo) {
    if(todo) {
        $(this).data('todo', todo);
    }
    else {
        return $(this).data('todo');
    }
}
但是,只添加这些代码是不够的,因为,没有人知道 jQueryElement 添加了 data() 方法。我们需要把它添加到 interface jQueryElement 中:

interface jQueryElement {
    data(name: string): any;
    data(name: string, data: any): jQueryElement;

    todo(): Todo;
    todo(todo: Todo): jQueryElement;
}
但是,我们不希望这么做,如果这么做,就不叫plugin了,因为,每添加一个方法,都要修改jQueryElement的源代码。

可以这么写:

interface jQueryElement {
    data(name: string): any;
    data(name: string, data: any): jQueryElement;
}

interface jQueryElement {
    todo(): Todo;
    todo(todo: Todo): jQueryElement;
}
这不会造成 interface jQueryElement 的重复定义,第二个定义只是给第一个定义添加了两个method。我们可以添加无数个 interface jQuery 定义。

4. enum

interface Todo {
    name: string;
    state: number; /* New=1, Active=2, Complete=3, Deleted=4 */
}
Todo 有四种状态,可以用number来表示。但我们希望它有更好的可读性,因为,遇到下面的代码,不容易猜测它的意图:

function deletTodo(todo: Todo) {
    if(todo.state != 3) {
        throw "Can't delete incomplete task!";
    }
}
可以使用 enum 关键字,定义新的类型:

enum TodoState {
    New = 1,
    Active = 2,
    Complete = 3, 
    Deleted = 4
}

interface Todo {
    name: string;
    state: TodoState; 
}

function deletTodo(todo: Todo) {
    if(todo.state != TodoState.Complete) {
        throw "Can't delete incomplete task!";
    }
}

5. 匿名类型

回顾一下前面写的 totalLength 函数:

function totalLength(x: (string | any[]), y: (string | any[])): number {
    var total: number = x.length + y.length;
    return total;
}
这个参数列表并不完美,其实,我们只是希望传入的参数带有 number 类型的 length 属性,可以这么写:

function totalLength(x: {length: number}, y: {length: number}): number {
    var total: number = x.length + y.length;
    return total;
}

{ length: number }  定义了一个匿名的 interface。

6. Indexer


第2行代码,它给 [ ] 定义了明确的signature,有了这个定义,最后一行才会出现上下文提示,TypeScript 才知道 comments 变量是个 string[ ] 。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值