typescript - 连接字符串作为打字稿中对象的键?
问题描述
假设我有以下 JS 代码:
export const giveMeFunctions = (namePrefix, number) => {
const functionA = (x) => number + x;
const functionB = (x, y) => number * x - y;
return {
[`${namePrefix}Add`]: functionA,
[`${namePrefix}MultSub`]: functionB,
};
}
// This is handy because I can then do:
const {piAdd, piMultSub} = giveMeFunctions('pi', Math.PI);
const {eAdd, eMultSub} = giveMeFunctions('e', Math.E);
// No confusion between variable names, and object interpolation makes it easy to use
但是,我想不出一种在 Typescript 中键入此函数的返回值的好方法。正如你所看到的,这两个键有不同的类型,所以我不能简单地做类似的事情
const giveMeFunctions<N extends string> = (number: number): {
[key: string]: Function;
} => {...}
因为这将允许意外交换 和 的functionA
参数functionB
。在我看来,这应该可以通过 Typescript 实现,因为这在编译时都是可能的。例如,如果我们简单地取出连接步骤,这将很容易实现:
export const giveMeFunctions<T extends string> = (number: number): Record<T, string> => {...}
我期望的工作将是:
const giveMeFunctions<N extends string> = (number: number): {
[N + 'Add']: string,
[N + 'MultSub']: string,
} => {...}
甚至:
const giveMeFunctions<N extends string> = (namePrefix: N, number: number): {
[N + 'Add']: string,
[N + 'MultSub']: string,
} => {...}
但是这两个都抱怨:
TS1170: A computed property name in a type literal must refer to an expression whose type is a literal type or a 'unique symbol' type.
有什么方法可以通过用户指定的字符串和硬编码后缀的串联定义的键来实现对象类型的预期效果?
解决方案
你可以这样做:
const record = <
Prop extends PropertyKey,
Value extends (...args: any[]) => any
>(prop: Prop, value: Value) =>
({ [prop]: value }) as Record<Prop, Value>
export const giveMeFunctions = <
T extends string,
N extends number
>(namePrefix: T, number: N) =>
({
...record(`${namePrefix}Add`, (x: N) => number + x,),
...record(`${namePrefix}MultSub`, (x: N, y: N) => number * x - y),
})
const result = giveMeFunctions('pi', Math.PI);
result.piAdd // (x: number) => number
result.piMultSub // (x: number, y: number) => number
record
功能可以解决问题。默认情况下,具有类似计算属性的对象{[prop]:key}
被解析{[props:string]:any type}
。
您可能已经注意到,我使用类型转换 as Record<Prop, Value>
来避免这种行为
推荐阅读
- node.js - 如何使用 socket.io 库区分客户端 TCP 套接字和客户端 websocket?
- android - 如何在 Android Studio 3.3 canary 13 中使用 MapView?
- c++ - 为什么默认情况下大多数对的实现不使用压缩(空基优化)?
- reverse-engineering - 在 IDA PRO 7 中加载跟踪文件时出错
- python - Python 3 高分标签显示 0 而不是显示来自 Pickle 的值
- java - Spring Boot 2+ Thymeleaf 3.0.10 异常处理 - 无法返回 error.html
- go - 无法扩展数组以作为多个参数传递
- cassandra - DCAwareRoundRobinPolicy 与 RoundRobinPolicy
- java - ORA-12505, TNS:listener 目前不知道服务器上连接描述符中给出的 SID
- c - C - 如何 (*(void (*)()) 编码); 在没有任何调用的情况下在 C 程序中运行