繁体   English   中英

Typescript 错误:扩展推断类型可防止 TS Linting 错误(提供了 Playground 示例)

[英]Typescript Bug: Extending An Inferred Type Prevents TS Linting Errors (Playground Example Provided)

我有一个名为myStyles的函数,它接受一个参数。 此参数是一个包含baseStyles对象和styleVariants对象的对象。 它只是返回styleVariants对象。

function myStyles<StyleVariants extends StyleVariantsStructure>(params: {
  baseStyles: AllowedStyles;
  styleVariants: StyleVariants;
}): StyleVariants {
  return params.styleVariants;
}

它是这样调用的:

myStyles({
  baseStyles: {
    color: 'red',
    backgroundColor: 'red',
  },
  styleVariants: {
    color: {
      red: {
        color: 'red',
        backgroundColor: 'red',
      },
    },
  },
});

baseStyles对象的类型为AllowedStyles ,它决定了我们允许使用哪些 css 属性和值。 这很完美,如果在调用myStyles函数时 CSS 属性或值拼写错误,我们会得到正确的 TS 错误,例如

type AllowedStyles = {
  color?: 'red';
  backgroundColor?: 'red';
};

styleVariants对象的类型为StyleVariantsStructure 这实质上决定了它应该接受一个或多个包含AllowedStyles嵌套对象,例如

type StyleVariantsStructure = {
  [k: string]: {
    [k: string]: AllowedStyles;
  };
};

myStyles函数中,我们对styleVariants参数对象使用类型推断。 这意味着,我们会自动获取传递给myStyles函数的styleVariants的确切类型。 然后我们使用styleVariants类型作为函数的返回类型。 这对我们来说是必需的,因为我们需要知道myStyles的确切返回类型。 这是我们的功能:

function myStyles<StyleVariants extends StyleVariantsStructure>(params: {
  baseStyles: AllowedStyles;
  styleVariants: StyleVariants;
}): StyleVariants {
  return params.styleVariants;
}

这是类型推断返回类型的示例,取自我用来演示此问题Typescript 游乐场

在此处输入图片说明

问题

如您所见,我需要使用StyleVariantsStructure类型来限制在styleVariants对象中传递的styleVariants ,例如我们必须只接受AllowedStyles 但是,我们还需要使用从styleVariants推断出的类型作为myStyles函数的返回类型。 我试图通过使用StyleVariants extends StyleVariantsStructure来解决这个StyleVariants extends StyleVariantsStructure 这在一定程度上起作用,但是在调用myStyles时, styleVariants参数对象中未突出显示某些 Typescript 错误。

例如,如果color拼写错误,我们不会得到 TS 错误:

在此处输入图片说明

但是,我确实得到了类型建议:

在此处输入图片说明

而且,如果值拼写错误,我确实会收到错误消息:

在此处输入图片说明

本质上,对我来说,似乎我需要找到一种替代方法来对styleVariants对象使用类型推断,同时还使用StyleVariantsStructure类型对其进行限制。 对此的任何帮助将不胜感激。

Typescript 操场中问题的最小演示

严格来说,这看起来是正确的,但需要哄着 TS 去检查它。 例如,使用 console.log() 将调用包装在 Playground 中会生成您想要的类型检查。

TS 作为检查器并不完美,因此在高度复杂的情况下它可能需要一些技巧才能检测到“正确”的解决方案 - 这就是!

问题似乎更像是 Typescript 的限制。 我发现的一种解决方法,对我们来说是一个完整的解决方案,如下所示:

function myStyles<StyleVariants>(params: {
  baseStyles: AllowedStyles;
  styleVariantKeys: StyleVariants;
  styleVariants: StyleVariantsStructure;
}): StyleVariants {
  return params.styleVariantKeys;
}
  1. styleVariantsKey对象添加到myStyles函数参数中
  2. 从中推断类型
  3. styleVariantsStyleVariantsStructure类型

这允许您按预期进行类型检查,并允许您从styleVariantsKey返回推断的类型。 但当然这意味着你必须有两个相同的对象,在我们的例子中这不是什么大问题,因为我们实际上不需要myStyles返回嵌套的样式对象,只需要变体名称。 所以我们的函数调用看起来像这样:

myStyles({
  baseStyles: {
    color: 'red',
    backgroundColor: 'red',
  },
  styleVariantKeys: {
    color: ["red"],
  },
  styleVariants: {
    color: {
      red: {
        color: 'red',
        backgroundColor: 'red',
      },
    },
  },
});

所以,我花在它上面的时间比我预期的要多,但我们来了。 如果您需要突出显示错别字,您应该基于 AllowedStyles 的 StyleVariants,例如:

type AllowedStyles = {
  color: 'red' | 'green';
  backgroundColor: 'red';
};

type StyleVariants = {
  [K in keyof AllowedStyles]?: AllowedStyles[K] | Partial<Record<AllowedStyles[K], Partial<AllowedStyles>>>
}

type StyleVariantsStructure = {
  baseStyles: AllowedStyles
  styleVariants: StyleVariants
}

function myStyles(params: StyleVariantsStructure):StyleVariants {
  return params.styleVariants;
}

StyleVariants 基于 AllowedStyles 结构和值,它包含 AllowedStyles 的所有属性,但它们是可选的。 每个属性的类型分别在 AllowedStyles 类型的属性中提供,或者它是一个对象,其键是 AllowedStyles 中提供的每个类型的属性,其类型又是 AllowedStyles,所有属性都是可选的。 希望你能明白!

打字稿游乐场

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM