【问题标题】:Map array of values to generic type in Typescript将值数组映射到 Typescript 中的泛型类型
【发布时间】:2023-04-04 23:02:01
【问题描述】:

我正在尝试创建一个函数来将字符串值数组映射到 Typescript 中的泛型类型。数组中值的索引与对象中的键具有相同的索引。例如:

我有一个Person 接口

interface Person {
    lastName: string;
    firstName: string;
}

一组值

const values = ['foo', 'bar']

而想要的结果是Person的实例

{
    lastName: 'foo',
    firstName: 'bar'
}

所需的函数类型应如下所示

const parse = <T extends Record<string, string | undefined>>(values: Array<string | undefined>)<T> => {
  ...
}

const result: Person = parse(['foo', 'bar']);

将 2 个数组映射到一个对象没有问题,但我希望输入返回的泛型以使事情变得更容易。 Object.keys(T)for key in T 之类的东西不起作用,因此很难获得键的索引。

您可以传递具有 100 个属性的泛型和具有 5 个值的数组,并且只应分配前 5 个属性,其他属性为 null 或未定义。反之亦然,您可以传递具有 3 个属性的泛型和具有 100 个值的数组,但只使用前 3 个。该数组可以包含undefined or null

【问题讨论】:

  • 应该parse 总是期望两个元素数组?
  • 不,您可以传递具有 100 个属性和 5 个长数组的泛型,并且只应分配前 5 个,其他为未定义的空值。反之亦然,您可以传递具有 3 个属性和 100 个值的数组的泛型,但只使用前 3 个。

标签: typescript reflection typescript-generics


【解决方案1】:

您必须记住,在编译您的代码时,所有关于类型的信息都会被删除。这意味着在运行时,您的函数将不知道Person 及其属性。

要编写这样的函数,您需要向它提供一些有关将返回的对象的信息。一种可能的方法是定义一个类而不是接口,并向您的函数添加一个接受构造函数的参数。

class Person {
    lastName = ""
    firstName = ""
}

type Constructor<T> = { new(): T }

function parse<T>(constructor: Constructor<T>, values: unknown[]): T {
    const obj = new constructor()
    // now you can call Object.keys(obj) and the like
    // ...
}

const result = parse(Person, ['foo', 'bar'])

【讨论】:

  • 嘿洛里斯,谢谢你的回答!但是当我从new constructor() 检查obj 时,属性没有初始化,所以Object.keys(obj) 返回一个空数组
  • 我用你的代码玩了一下,我找到了丢失的部分。你需要给类中的成员一个默认值,比如lastname!: string = ''。然后就可以了!
  • 确实,未初始化的类属性在编译时可能会被跳过,因此给它们一个默认值可能会更好。但是,在这种情况下,您应该删除感叹号。我编辑了我的答案。
猜你喜欢
  • 2018-06-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-05
  • 1970-01-01
  • 1970-01-01
  • 2021-03-28
相关资源
最近更新 更多