Vel*_*dan 0 iteration mapping types typescript
我正在研究 at 对象的简单映射器。它应该接受对象属性的数组并返回这些属性值的数组。它工作正常,但对于 Typescript,我无法保存返回值的类型顺序。
这是例子
import { createStore, Store as FriendsStore } from "./mobx_react_lite_store";
import { createAccountsStore, AccountsStoreType } from "./accountsStoreLite";
type RootObj = {
friendsStore: FriendsStore,
accountsStore: AccountsStoreType
};
const rootStore: RootObj = {
friendsStore: friendsStore,
accountsStore: accountsStore
};
function pickStores<T, K extends keyof T>(rootStore: T, keys: K[]): T[K][] {
return keys.map((key: K) => {
const store = rootStore[key];
if (!store) {
throw new Error(`Can't find the store with name ${key} in rootStore. Myabe yo've forgottent
to add this store to the rootStore.`);
}
return store;
})
}
Run Code Online (Sandbox Code Playgroud)
当我尝试仅用一家商店来调用它时,它对前任来说就像一个魅力
// Works fine. It shows that accountsStore has AccountsStoreType
const [ accountsStore ] = pickStores(rootStore, ["accountsStore"]);
// Works fine. It shows that accountsStore has friendsStore type
const [ friendsStore ] = pickStores(rootStore, ["friendsStore"]);
Run Code Online (Sandbox Code Playgroud)
但是当我尝试用 2 个存储调用它时,返回的类型不保持某些顺序。所以friendsStore可能是friendsStore 或AccountsStoreType。同样对于accountsStore
const [ friendsStore, accountsStore ] = pickStores(rootStore, ["friendsStore", "accountsStore"]);
Run Code Online (Sandbox Code Playgroud)
是否可以为每个被破坏的财产保存正确的类型?谢谢你的帮助。
UPDATE lukasgeiter提供了正确的答案,但 Typescript 有一些有趣的技巧。我调查了它们,查找了一些文档等,以下是了解这些功能的有用资源:
希望此信息对某人有所帮助。
为了解决这个问题,我们必须弄清楚两件事......
为了能够使用数组中元素的各个类型,keys我们需要 TypeScript 将其视为元组:
当前 TypeScript 将参数的类型推断keys为:
("friendsStore" | "accountsStore")[]
Run Code Online (Sandbox Code Playgroud)
然而,我们想要的是这样的类型:
["friendsStore", "accountsStore"]
Run Code Online (Sandbox Code Playgroud)
为了实现这一点,有几种解决方案:
最简单但也是最详细的选项是将数组转换为元组:
<["friendsStore", "accountsStore"]>["friendsStore", "accountsStore"]
Run Code Online (Sandbox Code Playgroud)
或者,我们也可以将数组转换为const. 这会将其转换为readonly元组:
<const>["friendsStore", "accountsStore"] // -> readonly ["friendsStore", "accountsStore"]
Run Code Online (Sandbox Code Playgroud)
如果我们更改keys为剩余参数,TypeScript 会将其类型推断为元组。继续阅读以查看其实际效果。
使用正确类型的元组,我们可以构造一个返回类型,它将键映射到以下类型T:
{ [I in keyof K]: T[keyof T & K[I]] }
Run Code Online (Sandbox Code Playgroud)
[I in keyof K]循环遍历数组的元素keys。I是索引而不是元素本身。K[I]获取元素的类型T[keyof T & K[I]]K[I]在 上查找属性的类型T。我必须添加keyof T &才能满足编译器的要求。如果丢失它会抱怨 that K[I]is not a key of T,即使我们知道情况总是如此。我创建了两个版本的代码,其中一个版本应该适用。一种使用剩余参数,另一种使用const强制转换。
不幸的是我不得不any在函数内部引入强制转换。也许可以将其转换为更具体的内容,但这是我能找到的最好的。
请注意由于剩余参数而导致我们调用函数的方式发生了变化
function pickStores<T, K extends (keyof T)[]>(rootStore: T, ...keys: K): { [I in keyof K]: T[keyof T & K[I]] } {
return keys.map((key: keyof T) => {
// ...
}) as any;
}
const [ friendsStore, accountsStore ] = pickStores(rootStore, "friendsStore", "accountsStore");
Run Code Online (Sandbox Code Playgroud)
function pickStores<T, K extends readonly (keyof T)[]>(rootStore: T, keys: K): { [I in keyof K]: T[keyof T & K[I]] } {
return keys.map((key: keyof T) => {
// ...
}) as any;
}
const [ friendsStore, accountsStore ] = pickStores(rootStore, ["friendsStore", "accountsStore"] as const);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2045 次 |
| 最近记录: |