javascript - 打字稿:缩小映射类型不适用于泛型
问题描述
问题:我想编写一个将对象和属性名称作为参数的函数。我想要实现的是只接受具有特定类型的属性的属性名称。
示例:在一个人对象中,我有字段名称:字符串和年龄:数字,然后我的函数应该只能使用参数(人,'名称')调用。这可以通过创建这种类型来实现:
export type OnlyPropertiesWithSpecificType<TYPE, T> = {
[K in keyof T]: T[K] extends TYPE ? K : never;
}[keyof T];
当访问函数内部的属性时,属性值的类型应该受到如下约束:
type Person = {
name: string;
age: number;
};
function somePersonFunction(obj: Person, param: OnlyPropertiesWithSpecificType<string, Person>): string {
return obj[param]; // works, obj[param] is of type 'string'
}
但是,当我尝试生成函数时,它不再受类型约束:
function someGenericFunction<T>(obj: T, param: OnlyPropertiesWithSpecificType<string, T>): string {
return obj[param]; // doesn't work: "TS2322: Type 'T[{ [K in keyof T]: T[K] extends string ? K : never; }[keyof T]]' is not assignable to type 'string'."
}
这很令人困惑,因为编译器仍然只接受属于“字符串”类型的属性的属性名称作为参数:
someGenericFunction(person, 'name'); // works
someGenericFunction(person, 'age'); // doesn't work
我尝试了什么:
- TS 版本 3.4.5 和 4.1.2。
- T 的各种变体,即 T 扩展对象
我用上面的例子创建了一个沙箱:https ://codesandbox.io/s/typescript-forked-ypy0b
我该如何解决这个问题?
解决方案
看起来 TS 还没有解决,它总是会someGenericFunction
返回 a string
,即使在实践中它总是会。
但是,除非您绝对需要: string
from 的返回类型注释someGenericFunction
,否则您可以省略它,您的代码将按预期工作。
function someGenericFunction<T>(
obj: T,
param: OnlyPropertiesWithSpecificType<string, T>
) {
return obj[param]; // inferred return type is T[OnlyPropertiesWithSpecificType<string, T>]
}
当使用实际类型调用时,TS 确实推断出它T[OnlyPropertiesWithSpecificType<string, T>]
总是可以分配给string
,这就是函数起作用的原因。
推荐阅读
- python - Plotly:将等高线图更改为 3-d 曲面
- c# - 我怎么做DoSomething???方法一种通用方法?
- asp.net-core-webapi - .net core webapi启动时如何预加载数据?
- postgresql - 什么是带括号的别名(类似于“FROM ... a(m)”)?
- javascript - 我如何重用反应组件但颜色不同?
- java - 使用 OneToMany 标签时.. EntityManager 没有持久性提供程序 - Hibernate JPA
- reactjs - FileReader - 存储更新后如何更新本地状态?
- javascript - Puppeteer.js:获取带有给定文本的链接的 href 属性
- javascript - 如何在 React 中访问其他组件的数据
- excel - 在 Excel VBA 中使用变量设置范围