【问题标题】:TypeScript template literal typesTypeScript 模板文字类型
【发布时间】:2022-02-21 08:51:08
【问题描述】:

去年Sam Stephenson(前 Basecamp/HEY)发布了一个very interesting tweet,关于他正在研究的stimulus js 库的一些发展,不幸的是,由于最近的basecamp fallout events,它从未见识过。

使用 TypeScript 模板文字类型 ????。 这是一个示例,展示了我们如何映射刺激控制器的 static targets = [...] 数组到所有的接口 生成的属性:

我最近一直在研究一些 Typescript,并试图破译那条特定的推文,但它似乎超出了我目前的理解水平。我在上一篇文章中已经尝试了解NamedPropertytypehere,但我仍然很困惑。

那么,谁能给我解释一下下面的代码?

type NamedProperty<Name extends string, T>
  = { [_ in 0 as Name]: T }

type UnionToIntersection<T>
  = (T extends any ? (x: T) => any : never) extends (x: infer R) => any ? R : never
type ValueOf<T>
  = T[keyof T]

type TargetPropertyGroup<Name extends string>
  = NamedProperty<`has${Capitalize<Name>}Target`, boolean>
  & NamedProperty<`${Name}Target`, Element>
  & NamedProperty<`${Name}Targets`, Element[]>

// This type troubles me the most
type TargetProperties<Names extends string[]>
  = UnionToIntersection<ValueOf<{ [Name in Names[number]]: TargetPropertyGroup<Name> }>>

let controller!: TargetProperties<[ "form", "input", "result"]>

// Magical autocomplete happens here just after the dot!
let result = controller.

提前致谢!

【问题讨论】:

    标签: typescript template-literals mapped-types


    【解决方案1】:

    让我们从零碎开始,然后尝试得到完整的东西。 你已经得到了what NamedProperty type。它可以让我们定义一个对象有一些属性和这个属性值的类型。

    UnionToIntersection&lt;T&gt; 将联合变为交叉。

    type A = UnionToIntersection<{ a: number } | { b: string }>; 
    // infers as { a: number } & { b: string };
    

    您可以在 this question 中找到有关其工作原理的详细说明。

    ValueOf&lt;T&gt; 接受一个类型并返回值类型的联合。

    type B = ValueOf<{ a: number; b: string }>;
    // infers as number | string;
    

    TargetPropertyGroup&lt;Name extends string&gt; 接受一个字符串并返回一个对象类型,该对象包含三个属性,其名称基于传递的字符串构造,值类型是预定义的。如您所见,它使用template literals types

    现在TargetProperties&lt;Names extends string[]&gt;

    { [Name in Names[number]]: TargetPropertyGroup&lt;Name&gt; }iterates 覆盖作为类型参数传递的所有值并应用TargetPropertyGroup,以便对于传递给TargetProperties 的每个字符串,它会生成一个包含三个属性的类型。

    type C<Names extends string[]> = { [Name in Names[number]]: TargetPropertyGroup<Name> };
    let test = C<["form", "input", "result"]>;
    // infers as 
    // {
    //    form: TargetPropertyGroup<"form">;
    //    input: TargetPropertyGroup<"input">;
    //    result: TargetPropertyGroup<"result">;
    // }
    

    最后两个步骤将ValueOf&lt;T&gt; 应用于此,如e 所知,将值类型作为联合返回:TargetPropertyGroup&lt;"form"&gt; | TargetPropertyGroup&lt;"input"&gt; | TargetPropertyGroup&lt;"result"&gt; 并应用UnionToIntersection 将类型转换为交集。结果类型看起来像一个对象,每个字符串包含三个字段,传递给TargetProperties

    【讨论】:

      猜你喜欢
      • 2021-08-28
      • 1970-01-01
      • 1970-01-01
      • 2021-07-21
      • 1970-01-01
      • 2018-03-19
      • 1970-01-01
      • 2022-06-17
      • 2021-10-24
      相关资源
      最近更新 更多