看看你的代码沙盒代码,看起来
keyof typeof slice.actions
没有足够的通用性来表达您要做的事情。尽管
slice
T
延伸
Slice
,当你评估
slice.actions
片
:
const actions = slice.actions; // CaseReducerActions<SliceCaseReducers<any>>
这很不幸,因为
keyof CaseReducerActions<SliceCaseReducers<any>>
(又名
keyof Slice['actions']
string | number
而不是你传递的特定密钥
T
:
type KeyofSliceActions = keyof Slice['actions'];
// type KeyofSliceActions = string | number
在属性查找时,将泛型值扩展到其约束可能有利于性能,但会导致一些不希望出现的情况,例如这种情况。看见
microsoft/TypeScript#33181
对于相关问题。
理想情况下,当您查找
actions
类型的值上的属性
T
,编译器会将结果视为
lookup type
T['actions']
自动地
,但您可以要求编译器使用类型批注执行此操作:
const genericActions: T['actions'] = slice.actions; // this is acceptable
切片动作
在剩下的代码中,使用
genericActions
,打字将按您希望的方式进行:
const getActions = <T extends Slice>(slice: T) => {
const genericActions: T['actions'] = slice.actions; // this is acceptable
const keys = Object.keys(genericActions) as Array<keyof typeof genericActions>;
return keys.reduce(
(accumulator, key) => {
accumulator[key] = `${slice.name}/${key}`;
return accumulator;
},
{} as Record<keyof typeof genericActions, string>
);
};
// const getActions: <T extends Slice<any, SliceCaseReducers<any>, string>>(
// slice: T) => Record<keyof T["actions"], string>
(旁白:
keyof typeof genericActions
可以缩短为
keyof T['actions']
)你可以看到
getActions()
现在返回
Record<keyof T["actions"], string>
,一种取决于
T
.
让我们看看它是否有效:
const actions = getActions<typeof issuesDisplaySlice>(issuesDisplaySlice);
// const actions: Record<"displayRepo" | "setCurrentPage" | "setCurrentDisplayType", string>
actions.displayRepo.toUpperCase(); // okay
actions.displayTypo.toUpperCase(); // error!
// ---> ~~~~~~~~~~~
// Property 'displayTypo' does not exist on type
// 'Record<"displayRepo" | "setCurrentPage" | "setCurrentDisplayType", string>'.
// Did you mean 'displayRepo'?
Playground link to code