【问题标题】:Generic mapping of types in typescript打字稿中类型的通用映射
【发布时间】:2018-06-16 06:37:45
【问题描述】:

让我们想象一下 T 型:

type T = {
  prop1: (s: S) => T1,
  prop2: (s: S) => T2,
  prop3: (s: S) => T3,
}

现在让我们想象一下 W 类型

type W = (s: S) => {
    prop1: T1,
    prop2: T2,
    prop3: T3,
}

很容易编写一个手动将 T 映射到 W 的函数,

是否可以在 typescript 中编写它的泛型类型 sefe 版本?

function x(t: T): W {
  return funtion(s: S) {
    prop1: t.prop1(s),
    prop2: t.prop2(s)
    prop3: t.prop3(s)
  }
}

缺少什么样的特征语言来促进这一点,比如高阶泛型类型?

【问题讨论】:

    标签: typescript generics type-conversion type-safety


    【解决方案1】:

    您确实可以在 TypeScript 中编写这个的通用版本:

    function x<S, V>(t: {[K in keyof V]: (s: S) => V[K]}): (s: S) => V {
      return function(s: S): V {
        const ret = {} as V;
        Object.keys(t).forEach((k: keyof V) => {
          ret[k] = t[k](s);
        })
        return ret;
      }
    } 
    
    const xSpecific: (t: T) => W = x; // okay
    

    注意VW 函数的返回类型。 (所以W 本质上与(s: S) =&gt; V 相同。)x 的输入是对应于Tmapped type:它与V 具有相同的键,但它的值是来自@ 的函数987654332@ 到V 的对应属性。

    由于 TypeScript 支持 inference from mapped types,因此您可以避免将函数输入设为映射类型而输出设为未映射类型。否则,您通常需要the proposed "extended typeof" feature 之类的东西才能从T 派生W。 (这可能是您所暗示的缺少的语言功能。)

    至于实现,我循环遍历t 的键并将每个函数t[k] 应用到输入s

    并且xSpecificx 相同,仅限于您发布的特定TW 类型。之所以可以编译,是因为 TypeScript 识别出通用的 x 是兼容的。


    现在是注意事项和细则。不幸的是,编译器无法直接从x 可靠地推断出S 的类型。如果你只是用T 输入调用通用x(),你会得到这个:

    declare const t: T;
    const w = x(t); // (s: {}) => { prop1: T1; prop2: T2; prop3: T3; }
    

    w 不完全是 W...它接受任何输入,而不仅仅是 S。如果你真的需要缩小输入的类型,你必须自己手动指定泛型参数:

    const w = x<S, {prop1: T1, prop2: T2, prop3: T3}>(t);
    

    这是丑陋的,或者通过断言或注释手动缩小生成的w

    const w: W = x(t);
    

    无论如何,希望对您有所帮助。祝你好运!

    【讨论】:

    • 确保它有帮助,基本上,你做了一件我从未做过的事情:) 女巫也许我应该更频繁地考虑一下,你在这种情况下使用了“作为”女巫。
    • 愚蠢的堆栈:) 我不得不分开我的答案......这个警告,你女巫 s:{} 签名,这并不酷,但我知道关于 Typescript 中的类似内容有几个问题GitHub。还有一件事,这个 V,它映射到 props 的正确返回值类型也不是那么明显。另一个教训是,我试图在 V 上声明通用约束,而不是直接声明参数 t 的形状,我脑子里还有太多 C# ;)
    • 在我的情况下,我可以将 s:S 放入 x 签名中并立即在 x 中调用此返回函数,因此可以忽略此警告。
    猜你喜欢
    • 2019-11-19
    • 2022-12-07
    • 1970-01-01
    • 2022-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-06
    • 1970-01-01
    相关资源
    最近更新 更多