当前位置: 代码网 > it编程>编程语言>Javascript > Typescript 转换类型操作索引映射类型IIMT模式学习

Typescript 转换类型操作索引映射类型IIMT模式学习

2024年05月15日 Javascript 我要评论
typescript 新的转换类型操作今天学习 typescript 的一种新的转换类型操作:索引映射类型——iimt(immediately indexed mapped t

typescript 新的转换类型操作

今天学习 typescript 的一种新的转换类型操作:索引映射类型——iimt(immediately indexed mapped type)

这个类型特别有意思,我们先看一个示例:

type tuple = [1, true, 'false']
type list = tuple[number]
  • 上面代码先创建了一个元组 tuple。
  • 然后通过 number 进行索引访问

得到的 list 为:

type list = 1 | true | 'false'

可以发现上面操作 通过索引映射,将操作类型转为了联合类型

如果是对象类型呢?

type person = {
    name: string
  age: number
}
type getvaluetype = {
  [k in keyof person]: person[k]
}[keyof person]

通过上面的转换,我们得到一个新的类型:

type getvaluetype = string | number

如果说我们想根据 person 类型创建一个新的类型,其结构为:

/**
 * | {
 *     key: string;
 *   } | {
 *     key: number;
 *   }
 * 
 */

修改 getvaluetype:

type getvaluetype = {
  [k in keyof person]: {
        key: person[k]
  }
}[keyof person]

上面的过程,可以分解为:

  • 先创建一个下列结构的类型
/**
 * {
 *   name: {
 *     key: string;
 *   },
 *   age: {
 *     key: number;
 *   }
 * }
 */
type temp = {
  [k in keyof person]: {
        key: person[k]
  }
}
  • 通过 iimt 创建目标类型
type getvaluetype = temp[keyof person]

通过上面两个示例,可以发现所谓的 iimt ,就是通过索引访问类型操作去迭代目标类型的 key 并为每个 key 创建一个新的类型。

通过 iimt 遍历联合类型

iimt 的特点在于,当你遍历联合类型的所有成员时,同时可以为你保留整个联合类型的上下文,不至于在遍历过程中丢失。下面我们基于一个联合类型创建一个新的联合类型

type fruit = "apple" | "banana" | "orange";
/**
 * | {
 *   thisfruit: 'apple';
 *   allfruit: 'apple' | 'banana' | 'orange';
 * }
 * | {
 *   thisfruit: 'banana';
 *   allfruit: 'apple' | 'banana' | 'orange';
 * }
 * | {
 *   thisfruit: 'orange';
 *   allfruit: 'apple' | 'banana' | 'orange';
 * }
 */
export type fruitinfo = {
  [f in fruit]: {
    thisfruit: f;
    allfruit: fruit;
  };
}[fruit];

如果不使用 iimt ,则上面会创建一个新的 对象类型。

我们可以看到新创建的 fruitinfo 类型是三个对象的联合类型,每个对象都有一个 thisfruit 属性和一个 allfruit 属性。thisfruit 属性是联合类型的特定成员,而 allfruit 属性是整个联合类型。

如果再加入其他工具类型,则又可以玩出许多花活,比如我们现在要实现在 allfruit 属性中,剔除 thisfruit,就可以这么写:

/**
 * | {
 *   thisfruit: 'apple';
 *   allfruit: 'banana' | 'orange';
 * }
 * | {
 *   thisfruit: 'banana';
 *   allfruit: 'apple' | 'orange';
 * }
 * | {
 *   thisfruit: 'orange';
 *   allfruit: 'apple' | 'banana';
 * }
 */
export type fruitinfo = {
  [f in fruit]: {
    thisfruit: f;
    allfruit: exclude<fruit, f>;
  };
}[fruit];

上面的代码在迭代 fruit 的时候,每次都会传入一个完整的 fruit 类型,也就是说每次 f 每次所能感知到的 fruit 都是独立的、互不干扰的,所以可以使用 exclude 从联合类型中删除当前的 f。

转换对象类型的联合类型

iimt 经常用于操作对象类型的联合类型,比如需要对联合类型中的每个对象的属性进行修改。

比如需要对 event 类型的每个对象类型的 type 属性加个前缀。

type event =
  | {
      type: "click";
      x: number;
      y: number;
    }
  | {
      type: "hover";
      element: htmlelement;
    };

如果说想直接通过遍历去修改联合类型中的对象类型,那么 ts 编译器会提示报错,比如说像下面这样:

type example = {
  // type 'event' is not assignable to
  // type 'string | number | symbol'.
  [e in event]: {};
};

因为你通过 e in event 遍历得到的其实是 每个对象类型,并不是 'string | number | symbol'。

这里我们可以通过 as 关键字在映射类型中操作类型

// 通过 omit 剔除 type 类型,对 type 属性单独操作
// 通过 交叉类型实现 更改 type 属性
type prefixtype<e extends { type: string }> = {
  type: `prefix_${e["type"]}`;
} & omit<e, "type">;
/**
 * | {
 *   type: 'prefix_click';
 *   x: number;
 *   y: number;
 * }
 * | {
 *   type: 'prefix_hover';
 *   element: htmlelement;
 * }
 */
type example = {
  [e in event as e["type"]]: prefixtype<e>;
}[event["type"]];

在这里,我们插入 as e['type'] 将键重新映射为我们想要的类型。然后使用 prefixtype 为每个对象的 type 属性添加前缀。

最后,我们 使用event['type'] 索引到映射类型,也就是click | hover——这样我们就得到了带前缀的对象的联合。

再看一些例子:

  • 转 css 单位为联合对象类型
type cssunits = "px" | "em" | "rem" | "vw" | "vh";
/**
 * | {
 *   length: number;
 *   unit: 'px';
 * }
 * | {
 *   length: number;
 *   unit: 'em';
 * }
 * | {
 *   length: number;
 *   unit: 'rem';
 * }
 * | {
 *   length: number;
 *   unit: 'vw';
 * }
 * | {
 *   length: number;
 *   unit: 'vh';
 * }
 */
export type csslength = {
  [u in cssunits]: {
    length: number;
    unit: u;
  };
}[cssunits];
  • 转 http 响应码与状态为联合类型
type successresponsecode = 200;
type errorresponsecode = 400 | 500;
type responsecode =
  | successresponsecode
  | errorresponsecode;
/**
 * | {
 *   code: 200;
 *   body: {
 *     success: true;
 *   };
 * }
 * | {
 *   code: 400;
 *   body: {
 *     success: false;
 *     error: string;
 *   };
 * }
 * | {
 *   code: 500;
 *   body: {
 *     success: false;
 *     error: string;
 *   };
 * }
 */
type responseshape = {
  [c in responsecode]: {
    code: c;
    body: c extends successresponsecode
      ? { success: true }
      : { success: false; error: string };
  };
}[responsecode];
—

总结

在 ts 中如果相对联合类型进行遍历操作,相较于官方文档中提到的基础操作,并不能很好的实现。但是 iimt 就可以解决这个问题,相当于 typscript 通过 iimt 提供了一个对联合类型遍历的能力,通过 iimt 可以实现对联合类型的单个类型进行操作,再结合其他类型体操基础动作,又可以玩出许多花样来。

参考:

以上就是typescript 转换类型操作索引映射类型iimt模式学习的详细内容,更多关于typescript iimt转换类型的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com