在TypeScript中,如何在函数的返回类型中将参数的值用作属性名称?

丹尼尔·吉布斯

我编写了一个函数,将对象转换为数组,其中数组的每个元素都包含对象的ID。目前,此代码可以很好地与以下代码配合使用:

const objectToArray = <T>(object: { [id: string]: T }): (T & { id: string })[] => {
  return Object.keys(object).map((key) => ({ id: key, ...object[key] }))
}

这将转换{ a: { value: 1 }, b: { value: 2 } }[{ id: 'a', value: 1 }, { id: 'b', value: 2 }]

我想做的是获取第二个参数idField,该参数是对象字段的名称,用作返回的对象中的ID字段。例如,如果idField具有该值,userId则结果将为[{ userId: 'a', value: 1 }, { userId: 'b', value: 2 }]

我已经在函数的逻辑中完成了此操作,但是我无法弄清楚返回类型应该是什么:

export const objectToArray = <T>(object: { [id: string]: T }, idField: string): ???[] => {
  return Object.keys(object).map((key) => ({ [idField]: key, ...object[key] }))
}

我尝试将return类型设置为,(T & { [idField]: string })[]但出现错误A computed property name in a type literal must refer to an expression whose type is a literal type or a 'unique symbol' type.

这有点复杂,因为(函数参数)是运行时,而类型只是编译时。没有什么可以阻止您将非常量字符串传递给的idField,而完全放弃了您在此处要求的类型检查。

但是,如果您确实向函数传递了常量字符串可以获得所需的类型安全

让我们从一个基本示例开始(在javascript中-省略的类型)-

function foo(prop) {
    return {
        [prop]: 42
    };
}

只是一个函数,它带有属性名称,并使用它来返回具有该属性的对象。本质上,这就是您在示例中显示的内容吧?您将如何输入?

function foo<T extends string>(prop: T): Record<T, number> {
    return {
        [prop]: 42
    } as Record<T, number>;
}

操场上尝试

这是如何运作的?我们首先确保prop是一个扩展字符串的类型(也可以是通用的T extends string | number | symbol),因为这是您需要prop用作属性的类型

然后,我们使用此类型创建返回类型Record<T, number>这与-

{
    [k in T]: number
}

您可以使用/或。

但是,该断言是必需的。由于打字稿无法始终将参数强制为编译时间常数。

这将使用在编译时已知的字符串正确键入check-

let s = foo('userName');
 // ^ Record<'userName', number>

s.userName; // all good
s.otherProp; // Property 'otherProp' does not exist on type 'Record<"userName", number>'

好的,现在让我们将其用于您的功能-

export const objectToArray = <T, K extends string>(
    object: { [id: string]: T },
    idField: K
): (T & Record<K, string>)[] => {
    return Object.keys(object).map(key => ({ [idField]: key, ...object[key] })) as (T & Record<K, string>)[];
};

请注意,我再次假设K(的类型idField)将是一个字符串-您可以使用,也可以根据使用情况将K extends string | number | symbol其任意组合。我还假设带有的属性的值Kstring,因此Record<K, string>

操场上尝试

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何在Mockito中基于参数属性返回不同的值?

如何在Laravel Eloquent中将变量用作属性名称

如何在MySQL中获取函数体,名称,参数和返回类型?

如何在Java 8中将CSV值用作构造函数参数

如何在TypeScript中声明函数的返回类型

函数如何在R中返回其名称和参数

如何在Delphi 10.2中将接口方法用作方法类型的参数

如何在TypeScript中将函数返回的类用作类型?

在TypeScript中,如何键入函数的参数而不是返回值?

如何在TypeScript中为函数参数设置参数名称和类型?

TypeScript:如何在带有rest参数的函数中返回条件类型?

函数参数是TypeScript类型中存在的属性

如何在Rust中将类型参数指定为函数参数?

如何在TypeScript中将函数的返回类型指定为名称空间类型,以便提出建议

如何使TypeScript基于返回值识别函数的参数类型?

TypeScript:如何根据函数参数类型设置函数返回值类型

如何在TypeScript中将模板文字类型用作返回类型属性

如何在TypeScript中将函数类型声明为参数

如何在TypeScript中将MobX状态树模型用作函数参数?

如何在Typescript中将类型变量用作具有相同名称的类型?

如何在Julia中将向量用作类型参数

在类中定义私有结构时,如何将其用作函数参数或返回类型?

如何在Typescript中将类型注入函数?

如何在C#中将变量的名称传递给函数并返回其值?

如何在ocaml中将函数参数和返回类型指定为List?

如何在 Typescript 中管理多个函数返回类型?

返回属性名称字符串文字值的 TypeScript 函数?

如何在 TypeScript 中接受我的函数的通用返回类型?

如何从函数参数中获取对象属性值作为类型