javascript - 使用 keyof 查找的 Typescript 界面模板
问题描述
我想要类似的东西
interface Operation<T, K extends keyof T> {
key: keyof T;
operation: 'add' | 'remove';
value: T[K];
}
但不需要K
作为模板传递;基本上,我希望能够做到:
interface User {
name: string;
age: number;
}
// this is valid
const operation: Operation<User> = {
key: 'name',
operation: 'add',
value: 'the value',
}
// this is valid
const operation: Operation<User> = {
key: 'age',
operation: 'add',
value: 123,
}
// this is not valid
const operation: Operation<User> = {
key: 'age',
operation: 'add',
value: '123', // type is wrong, should be number
}
我该怎么做呢?
解决方案
如果我们通过使用函数来改进创建对象的方式,就个人而言,我们可以。这个想法如下:
首先,创建类型获取任何属性的值类型:
type ValueType<T, K> = K extends keyof T ? T[K] : never;
然后定义Operation
类型:
type Operation<T, K> = {
key: K
operation: 'add' | 'delete'
value: ValueType<T, K>
}
现在关键是在这里定义构建函数而不是直接创建对象,因为我们热衷于阅读参数:
type BuildOperation<T> = <K>(arg: K) => (arg: Operation<T, K>) => Operation<T, K>
function build<T>(): BuildOperation<T> {
return (key) => (props) => ({
key,
...props,
});
}
最后,我们可以通过设置 keyas const
来使用我们的函数来确保 Typescript 不会推断为字符串:
type User = { name: string; age: number }
const obj = build<User>()('age' as const)({
key: 'age',
value: 20, // It will hint you this is number
operation: 'add',
});
推荐阅读
- vue.js - Vue 或 Webpack 编译的 JS 缓存管理
- c++ - 动态数组的实现
- xml - 如何通过 xml 配置 spring security 5.4.1 以使 oauth2 注销正常工作?
- python - Jupyter / Python — 有没有办法在每个 Jupyter 单元中自动运行 %%time 之类的魔术命令?
- python - Discord.py 响应反应
- c++ - 如何限制 rand 函数可以生成的数字。(分段故障)
- python-3.x - 如何使用 pandas 在 csv 文件的最后一行和特定列中插入文本?
- internationalization - 是否有从多个 .po 文件生成所有 .mo 文件的命令?
- javascript - 为 DT 数据表上的双击事件创建 R 闪亮绑定
- python - 在 pandas 中爆炸两列:ValueError