【问题标题】:How to use function overloading to implement a bidirectional mapping function?如何使用函数重载实现双向映射函数?
【发布时间】:2018-12-28 03:35:58
【问题描述】:

TL;DR

Try it online


我有两个联合类型(都是字符串字面量)和一个硬编码映射对象,它将这两种类型相互映射。

type Digit = '1' | '2'
type Alpha = 'a' | 'b'
const map: Record<Digit, Alpha> & Record<Alpha, Digit> = {
    '1': 'a',
    '2': 'b',
    'a': '1',
    'b': '2'
}

硬编码映射在用于单例值时效果很好。

let digit: Digit = '1'
let alpha = map[digit] // alpha is inferred as Alpha
let digit2 = map[alpha] // digit2 is inferred as Digit

用一个函数包装它,然后映射到一个数组上也是可以的。

let digitArr: Digit[] = ['1', '2']
let alphaArr = digitArr.map(d => map[d]) // inferred as Alpha[]

但是当我只想使用一个函数,通过重载,实现双向映射,即

digitArr.map(mapping) // returns Alpha[]
alphaArr.map(mapping) // returns Digit[]
// where digitArr and alphaArr is deterministically typed as Digit[] and Alpha[]

类型系统抱怨它,我不知道如何让它快乐。

我的函数定义:

function overloadedMapping(digit: Digit): Alpha
function overloadedMapping(alpha: Alpha): Digit
function overloadedMapping(key: Digit | Alpha): Digit | Alpha {
    return map[key]
}

此函数也适用于单例值,但在一种数组上失败。

let d = overloadedMapping('a') // d is of type Digit
let a = overloadedMapping('1') // a is of type Alpha
let arr = alphaArr.map(overloadedMapping) // arr is of type Digit[]. works? why?
let arr2 = digitArr.map(overloadedMapping) // type inference fails!! why?

一个有趣的观察:当重载声明顺序切换时,失败的数组映射也会交替出现。

Try it online(同第一个链接)

【问题讨论】:

  • 附注:枚举是 TypeScript 中已经内置的双向映射。您可以创建一个 (enum MyMap { Alpha = 0, Beta = 1}) 并访问键和值 (MyMap['Alpha'], MyMap[0])。
  • 嗨,卡罗尔,谢谢。虽然enum 确实提供了双向映射,但它不符合我的需求。映射的两边都需要是任意字符串文字,并且基于字符串的枚举不是双向映射的。而且,用一个函数映射数组是不可能的。

标签: typescript typescript-typings overloading


【解决方案1】:

当重载解析无法将您的回调与所需签名匹配时,您可以通过显式提供类型参数来告诉 TypeScript 您的意图:

let arr2 = digitArr.map<Alpha>(overloadedMapping)

现在您的转换将被视为(value: Digit, index: number, array: Digit[]) =&gt; Alpha

在这种情况下,选择不使用无点样式也有助于 TypeScript 匹配重载:

let arr2 = digitArr.map(digit => overloadedMapping(digit))

【讨论】:

    猜你喜欢
    • 2012-01-04
    • 2018-04-14
    • 2018-04-03
    • 2014-07-01
    • 1970-01-01
    • 2021-11-21
    • 2013-02-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多