【问题标题】:Pass parametric type as a type argument to another type in TypeScript or Flow将参数类型作为类型参数传递给 TypeScript 或 Flow 中的另一种类型
【发布时间】:2021-08-06 20:43:54
【问题描述】:

出于演示目的,请考虑以下类型:

type ToEnglish<A extends string> = 
  A extends "1" ? "one" :
  A extends "2" ? "two" :
  A extends "3" ? "three" :
  "etc";

type Convert<A extends string> =
  A extends `${infer C}${infer Tail}` ? 
    `${ToEnglish<C>}-${Convert<Tail>}` : "";

例如,Convert&lt;"12"&gt; 的结果是 "one-two-"

现在我想让它更通用并接受一个“翻译器”,例如上面的ToEnglish作为参数:

type Convert2<A extends string, Translator> =
  A extends `${infer C}${infer Tail}` ? 
    `${Translator<C>}-${Convert<Tail>}` : "";

这不起作用:Type 'Translator' is not generic. ts(2315)

如果我尝试写作:

type Convert3<A extends string, Translator<_>> = 

我收到:',' expected. ts(1005) &lt;_&gt;

: 有没有办法在 TypeScript、Flow 或另一个 JavaScript 超集中以某种方式将参数(通用)类型作为参数(参数)传递给另一种类型?
类似于高阶函数,但针对类型。

【问题讨论】:

  • TS 不支持更高种类的类型。 AFAIK Flow.js 确实
  • 我可能会为此更改为 Flow,让我将问题更改为也包括 Flow @captain-yossarian
  • 虽然您可以将类型构造函数作为泛型传递给类型实用程序flow.org/en/docs/types/utilities/#toc-objmap flowjs 不支持模板文字字符串
  • @captain-yossarian,嗯,它似乎对我不起作用:type Test&lt;N, F&gt; = F&lt;N&gt;,错误是 Cannot apply type because it is not a polymorphic type. [nonpolymorphic-type-app]
  • 你需要使用objectmap util type

标签: typescript flowtype typescript-generics higher-kinded-types higher-order-types


【解决方案1】:

我建议一种解决方案,该解决方案绕过必须直接将泛型类型作为类型参数传递。例如,通过使用本质上是翻译者的记录,您可以改为传递给定翻译者的名称并访问类型:

Playground

type ToEnglish<A extends string> = 
  A extends "1" ? "one" :
  A extends "2" ? "two" :
  A extends "3" ? "three" :
  "etc";

type ToSpanish<A extends string> = 
  A extends "1" ? "uno" :
  A extends "2" ? "dos" :
  A extends "3" ? "tres" :
  "etc";


type TranslatorMap<A extends string> = {
    English: ToEnglish<A>;
    Spanish: ToSpanish<A>;
}

type ConvertGeneric<A extends string, Translator extends keyof TranslatorMap<A>> =
  A extends `${infer C}${infer Tail}` ? 
    `${TranslatorMap<C>[Translator]}-${ConvertGeneric<Tail, Translator>}` : "";

type EnglishTest = ConvertGeneric<"12", "English">
type SpanishTest = ConvertGeneric<"12", "Spanish">


【讨论】:

  • 这是一个聪明的解决方法,谢谢。看起来目前在 TS 中没有更好的方法可以做到这一点:(
【解决方案2】:

这不是问题的直接答案。只是一个flowjs 的例子:

// @flow

type TypeConstructor = <V>() => {updated:V};

type Obj = {
  a: number,
  b: string
}

type Result = $ObjMap<Obj, TypeConstructor>

const ok:Result = {
  a: {updated:42},
  b: {updated:42}
}; // ok

const error:Result = {
  a: 42,
  b: 42
}; // error

您可能已经注意到,TypeConstructor 就像回调。

它检索type 并将其转换为另一个type。每个obj 键/值对都传递给TypeConstructor。在 TypeScript 中是不可能的,因为 TypeScript 需要为 TypeConstructor 显式泛型。

【讨论】:

  • 所以,TypeConstructor 不是参数类型,也不是类型函数,它的“输出”是常量,不依赖于它的参数。在我的示例中,例如 ToEnglish 是一个“类型函数”:根据在参数中传递给它的类型,它返回不同的结果类型。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-27
  • 1970-01-01
  • 2021-02-13
  • 1970-01-01
  • 2019-04-24
  • 2021-02-12
相关资源
最近更新 更多