typescript索引类型_TypeScript类型系统(2/5)-基本篇综合应用

a0cf36ca923355f12e26552458e62a12.png

本文是对TypeScript类型系统系列之基本篇的补充和实战,传送门。

咱们先从接口聊起

接口

应用1

如何定义接口类型为可调用?(类比Java8里的函数式接口),如下:

interface ActionById {
    (id: number): string
}

const testActionById = () => {
    const getActionById: ActionById = (id: number) => 'delete';
    const result = getActionById(1);
}

应用2

如何定义对象的成员数量不确定的属性,使用可索引类型表示。这个语言特性特别实用,在下篇的内容提到的索引类型,会看到类似的语法。

interface Phone {
    [name: string]: string
}

这时候,Phone类型表示任意多个字段名为string,字段值类型为string的字段。

应用3

接口必须和类搭配使用,通常通过接口能规范的只是类的实例方法和属性,TS还可以规范类的构造方法。

interface TaskConstructor {
    new (name: string , taskStatus: number);
}

const task: TaskConstructor = class Task {
    name: string;
    taskStatus: number;
    createTime: string;
    taskType: number;

    constructor(name: string , taskStatus: number){
    }
}

class类定义返回的就是该类构造方法的类型,这个特性让类的实例可组合,比如

interface TaskConstructor {
    new (name: string , taskStatus: number): ITask;
}

interface ITask {
    name: string 
    taskStatus: number
}

class TaskA implements ITask{
    name: string;
    taskStatus: number;

    constructor(name: string , taskStatus: number){
        console.log('generate TaskA');
    }
}

class TaskB implements ITask{
    name: string;
    taskStatus: number;

    createTime: string;
    taskType: number;

    constructor(name: string , taskStatus: number){
        console.log('create TaskB');
    }
}

const createTask = (task: TaskConstructor, name: string , taskStatus: number) => (new task(name, taskStatus))

const taskA: ITask = createTask(TaskA, 'A', 1);
const taskB: ITask = createTask(TaskB, 'B', 2);

上面createTask方法,让Task实例变得可动态化和可配置化。对类的实例化这个动作和实例的表示在代码的空间和时序上做了分离。

联合类型

联合类型、字面量类型/枚举的综合使用

给出一个场景:某个类型,字段A是否存在依赖于另一个字段B的值

比如下面定义OperationAction类型,当status字段值是‘add’时,存在addId字段,不存在removeId字段,当status字段值是‘remove’时,只存在removeId字段,而没有addId字段,怎么改进OperationAction类型?

type OperationAction = {
    status: 'add' | 'remove',
    taskName: string,
    addId?: number,
    removeId?: number,
}

OperationAction2是对OperationAction的改进

type OperationAction2 = {
    status: 'add',
    taskName: string,
    addId: number,
} | {
    status: 'remove',
    taskName: string,
    removeId: number,
}

我们把status字段的联合类型操作符|移动到了外层。使用时如这般:

const assertNever = (x: never): never => {
    throw new Error("Unexpected: " + x);
}

const testOperationAction2 = (action: OperationAction2) => {
    switch(action.status){
        case 'add':
            const aid = action.addId;
        break;
        case 'remove':
            const rid = action.removeId;
        break;
        default:
            assertNever(action);
    }
}

这里status字段除了使用字面量类型外,还可以使用枚举,同样能实现addId字段和removeId字段通过status字段值来区别

enum ActionType {
    Add,
    Remove,
}

type OperationAction3 = {
    status: ActionType.Add,
    taskName: string,
    addId: number,
} | {
    status: ActionType.Remove,
    taskName: string,
    removeId: number,
}

const assertNever = (x: never): never => {
    throw new Error("Unexpected: " + x);
}

const testOperationAction3 = (action: OperationAction3) => {
    switch(action.status){
        case ActionType.Add:
            const aid = action.addId;
        break;
        case ActionType.Remove:
            const rid = action.removeId;
        break;
        default:
            assertNever(action);
    }
}

上面所说的是,类型里的字段A的有无依赖另一个字段,如果是字段A的类型(比如string或者number),取决另一个字段B的值呢?同理,可以通过上述方法实现。

小结

TS的接口比Java 8的接口强大,额外多了可索引类型表示,直接可调用,构造函数可实例等诸多特性。

联合类型在使用是在TS里高频使用,大大增加了代码的类型动态化。

TS类型系列延伸阅读:

Ethan Ruan:TypeScript类型系统(3/5)- 进阶篇​zhuanlan.zhihu.com
165274daeb160b97805a9b7cc90d9e55.png
Ethan Ruan:TypeScript类型系统(4/5)-进阶篇综合应用​zhuanlan.zhihu.com
165274daeb160b97805a9b7cc90d9e55.png
Ethan Ruan:TypeScript类型系统(5/5)-类型编程篇​zhuanlan.zhihu.com
165274daeb160b97805a9b7cc90d9e55.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值