Typescript 中带有泛型的 Rest 运算符

Rest operator with generics in Typescript

考虑以下代码...

我希望扩展运算符是有效代码,但结果并非如此。我希望有 Typescript 专业知识的人可以就为什么会这样提供建议...

export default function convertToGlobalFragment<
  T extends basicFragmentRecipe_T
>(
  fragmentFactory: (recipe: T) => configFragment_I,
  recipe: T & { matchingRules: globalMatchingRules_T }
): globalConfigFragment_I {

  let {
    matchingRules,
    ...restOfRecipe
  }: { matchingRules: globalMatchingRules_T, restOfRecipe: T } = recipe;

}

错误代码

Property 'restOfRecipe' is missing in type 'basicFragmentRecipe_T & { matchingRules: globalMatchingRules_T; }' but required in type '{ matchingRules: globalMatchingRules_T; restOfRecipe: T; }'.ts(2741)

recipebasicFragmentRecipe_T 加上 { matchingRules: globalMatchingRules_T } 并且 basicFragmentRecipe_T 似乎根本没有 restOfRecipe 属性。

您需要指定相同的目标类型才能分配 recipe:

let {
    matchingRules,
    ...restOfRecipe
  }: { matchingRules: globalMatchingRules_T } & T = recipe;
let {
    matchingRules,
    ...restOfRecipe
  }: { matchingRules: globalMatchingRules_T, restOfRecipe: T } = recipe;

这部分是错误的,因为食谱不包含名为 restOfRecipe 的 属性 - 它是 { matchingRules: globalMatchingRules_T } & T - 其中 T 可分配给 basicFragmentRecipe_T

您可以在没有此代码的情况下提取 restOfRecipe - 让 TS 完成工作:

  let { matchingRules, ...restOfRecipe } = recipe;

现在 restOfRecipe 的类型是:

Pick<T & { matchingRules: globalMatchingRules_T; }, Exclude<keyof T, "matchingRules">>

让我们分解一下。

食谱类型是T{ matchingRules: globalMatchingRules_T; }

的组合

要从此类型中获取 'matchingRules' 以外的属性 - 我们需要从 T{ matchingRules: globalMatchingRules_T; } 中排除 matchingRules。由于后面的部分总是包含 matchingRules,我们可以跳过检查组合,只看 Exclude<keyof T, "matchingRules" 来获取 T 的键而不用 'matchingRules'.

最后我们使用 Pick<T, K>Recipe 的类型中选择 T 的键(没有 matchingRules),得到上面的结果。