typescript - 当方法按预期工作时,为什么不能推断出正确的类型?
问题描述
这是 TS Playground 的链接,使用评论解释我的问题。我决定不将整个内容作为内联代码包含在内,因为我想防止不必要的滚动。
问题:
虽然该normalize
方法按预期工作(如操场所示),但当使用泛型类型调用它时,它的结果不会根据传入的泛型类型值推断类型,而是联合所有可能的值。
我尝试过的:
我尝试玩type NormalizeFn
,还留下了我在操场上尝试过的示例,但不仅没有奏效,还因为我输入错误而开始对我大喊大叫。
我正在尝试修复的方法:
注意:这只是游乐场链接中包含的内容的一部分
// Converts a Record<entity_id, entity_value_object>
// into Array<entity_value_object & {id: entity_id}>
// Basically moves the id as key into the value object so that
// we add the id field back into the result that didn't have the id.
type NormalizeFn = <
// i.e. I tried below and things similar to it, but it gives errors as I am not able to
// get it working without ts yelling at me.
// ObjType extends Record<string, Record<string, any>> | undefined = { id: Record<string, any> },
ObjType extends object | undefined = object,
KeyId extends string = 'id'
>(
obj: ObjType,
keyPropName?: KeyId
) => ObjType extends Record<infer Key, infer Val>
? Array<Val & { [key in KeyId]: Key }>
: never;
const normalize: NormalizeFn = (obj, keyPropName) => {
return Object.entries(obj || {}).map(([key, val]) => {
return {
...val,
[keyPropName || 'id']: key,
};
});
};
一些测试展示了它是如何工作的:
// Normalize works as inteded:
const testFirestoreUserDataResult: FirestoreData['users'] = {
user_id: {
name: 'user_name'
},
user_id2: {
name: 'user_name2'
}
}
// Normalize tests showing its usage.
const normalizedUsers = normalize(testFirestoreUserDataResult);
normalizedUsers[0].id; // in VSCode this also infers 'user_id' | 'user_id2'
normalizedUsers[0].name;
const normalizedUsers2 = normalize(testFirestoreUserDataResult, 'customIdKey');
normalizedUsers2[0].id; // Fails as intended
normalizedUsers2[0].customIdKey; // in VSCode this also infers 'user_id' | 'user_id2'
normalizedUsers2[0].name;
问题1:有什么问题type NormalizeFn
?
问题2:可以type NormalizeFn
改进/写得更好吗?
我确信我错过了一些简单且可能是基本的东西,但我就是无法让它发挥作用。希望有人可以在这里指导我,感谢您的帮助!
解决方案
推荐阅读
- r - mutate() 基于在另一列中找到的不同长度的字符串向量的新列
- sql-server - 仅保留差异的 SQL Server 表
- excel - VBA 二维数组
- lua - Lua 有没有像样的开发者工具?
- swift - 如何垂直对齐表格视图单元格的所有内容?
- reactjs - 如何在 React 中创建多级选项列表?
- sql - 在存储过程中将运算符作为参数传递,同时防止 SQL 注入的风险
- dart - 如何在飞镖中生成oauth签名
- java - Spring Security 单元测试@PreFilter 和@PostFilter 的正确方法
- node.js - 使用cheerio,无法使用.attr 获取属性