【问题标题】:How to dynamicaly construct a type from multiple properties?如何从多个属性动态构造数据类型?
【发布时间】:2019-08-10 04:38:08
【问题描述】:

我正在研究 Typescript 中的高级类型,目前我所拥有的是一个 type x,它接受一个通用参数 props extends string。给定 props 的值是 name | age | email 这构造了以下类型:

{
  name: "name",
  age: "age",
  email: "email"    
}

上面的类型是由下面的类型定义生成的:

type x<Property extends string> = { [K in Property]: K }

我也有上述类型的类型构造函数:

let x = <props extends string>(p: props): x<props> => (<x<props>>{[p]: p})

我可以通过简单地将字符串类型的属性传递给函数x来生成类型:

x("name") // Type is x<"name">

我想做的是将多个属性传递给x,以这样的方式: x("name", "age", "email") 产生类型 x&lt;"name" | "age" | "email"&gt;

我知道我可以通过像这样重构 x 方法来实现:

let x = <props extends string>(...p: props[]): x<props> => null! // Don't know how to implement this

但我不知道如何从该输入构造一个具体对象,类似于(&lt;x&lt;props&gt;&gt;{[p]: p}),但遍历传递给x 的所有属性。

那么有没有办法遍历属性并动态构造一个类型?

【问题讨论】:

    标签: typescript types typescript-generics


    【解决方案1】:

    你只需要遍历 props 并将它们分配给一个新对象:

    type x<Property extends string> = { [K in Property]: K }
    
    
    let x = <props extends string>(...p: props[]): x<props> => {
        let result = {} as x<props>
        for (let k of p) {
            result[k] = k
        }
        return result;
    } 
    
    let a = x("name", "age") // Type is x<"name">
    console.log(a);
    

    没有神奇的语法可以在单个表达式中产生这个对象,所以我们使用类型断言来欺骗编译器{}x&lt;props&gt; 并在for 之后修复对象。有时类型断言是必要的,这是其中之一,因为我们有编译器没有的特殊信息(我们将在接下来的几行中将{} 转换为有效的x&lt;props&gt;

    或者更简洁的一行版本:

    let x = <props extends string>(...p: props[]): x<props> => p.reduce((o, k) => (o[k] = k, o), {} as x<props>);
    

    【讨论】:

    • 那我也可以用props.foreach(prop =&gt; ...),因为这是一个软件工程课程的学校项目。老师们不喜欢使用循环、ifs、else、for、whiles 等。所以有时我不知道什么是允许的。但我会认为循环没问题
    • @HarryStylesheet 如果你想让他们惊叹,请使用 reduce 版本:P
    • 我认为意志是这样的,整个课程都是关于制作函数组合、函子、幺半群和单子。
    • @HarryStylesheet 不……你需要在 TS 中为此编写命令式代码,没有任何意义:P.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-18
    • 1970-01-01
    • 2022-12-09
    • 1970-01-01
    • 1970-01-01
    • 2015-05-03
    • 1970-01-01
    相关资源
    最近更新 更多