Skip to content

MapTypes

约 399 字大约 1 分钟

2022-12-01

题目

实现 MapTypes<T, R>,它将对象 T 中的类型转换为由类型 R 定义的不同类型,R 的结构如下:

interface StringToNumber {
  mapFrom: string // 值为字符串的键的值
  mapTo: number // 将被转换为数字
}

示例:

interface StringToNumber { mapFrom: string, mapTo: number }
MapTypes<{ iWillBeANumberOneDay: string }, StringToNumber>
// gives { iWillBeANumberOneDay: number; }

请注意,用户可以提供一个联合类型:

interface StringToNumber { mapFrom: string, mapTo: number }
interface StringToDate { mapFrom: string, mapTo: Date }

MapTypes<{ iWillBeNumberOrDate: string }, StringToDate | StringToNumber>
// gives { iWillBeNumberOrDate: number | Date; }

如果我们在映射中不存在这种类型,就让它保持原样:

interface StringToNumber { mapFrom: string, mapTo: number }
MapTypes<{ iWillBeANumberOneDay: string, iWillStayTheSame: Function }, StringToNumber>
// // gives { iWillBeANumberOneDay: number, iWillStayTheSame: Function }

解题思路

答案

type MapTypes<T, R extends { mapFrom: unknown, mapTo: unknown }> = {
  [P in keyof T]: T[P] extends R['mapFrom']
    ? R extends { mapFrom: T[P] }
      ? R['mapTo']
      : never
    : T[P]
}

验证

type 
cases
= [
Expect
<
Equal
<
MapTypes
<{
stringToArray
: string }, {
mapFrom
: string,
mapTo
: [] }>, {
stringToArray
: [] }>>,
Expect
<
Equal
<
MapTypes
<{
stringToNumber
: string }, {
mapFrom
: string,
mapTo
: number }>, {
stringToNumber
: number }>>,
Expect
<
Equal
<
MapTypes
<{
stringToNumber
: string,
skipParsingMe
: boolean }, {
mapFrom
: string,
mapTo
: number }>, {
stringToNumber
: number,
skipParsingMe
: boolean }>>,
Expect
<
Equal
<
MapTypes
<{
date
: string }, {
mapFrom
: string,
mapTo
: Date } | {
mapFrom
: string,
mapTo
: null }>, {
date
: null | Date }>>,
Expect
<
Equal
<
MapTypes
<{
date
: string }, {
mapFrom
: string,
mapTo
: Date | null }>, {
date
: null | Date }>>,
Expect
<
Equal
<
MapTypes
<{
fields
:
Record
<string, boolean> }, {
mapFrom
:
Record
<string, boolean>,
mapTo
: string[] }>, {
fields
: string[] }>>,
Expect
<
Equal
<
MapTypes
<{
name
: string }, {
mapFrom
: boolean,
mapTo
: never }>, {
name
: string }>>,
Expect
<
Equal
<
MapTypes
<{
name
: string,
date
: Date }, {
mapFrom
: string,
mapTo
: boolean } | {
mapFrom
: Date,
mapTo
: string }>, {
name
: boolean,
date
: string }>>,
]

参考