我正在用TypesScript构建一个Next.js应用程序,其中一种类型是:

type GetStaticPropsContext<Q extends ParsedUrlQuery = ParsedUrlQuery, D extends PreviewData = PreviewData> = {
    params?: Q | undefined;
    preview?: boolean | undefined;
    previewData?: D | undefined;
    locale?: string | undefined;
    locales?: string[] | undefined;
    defaultLocale?: string | undefined;
}

我想更改它,使localelocalesdefaultLocale永远不是undefined,以避免在任何地方编写as stringas string[]强制转换,因为在我的应用程序中,区域设置总是被定义的.

我试着创建一个这样的类型

type LocaleConfig = {
  locale: string
  defaultLocale: string
  locales: string[]
}

然后只需使用

export const getStaticProps: GetStaticProps = (
  context: GetStaticPropsContext & LocaleConfig
) { // do stuff }

但我得到了Type 'string | undefined' is not assignable to type 'string'.个错误.

我还试图创建一个扩展GetStaticPropsContext的接口,但除非我误解了它的工作原理,否则我还必须复制如下所示的泛型(这并不理想):

export interface NewGetStaticPropsContext<
  Q extends ParsedUrlQuery = ParsedUrlQuery,
  D extends PreviewData = PreviewData
> extends GetStaticPropsContext {
  params?: Q | undefined
  previewData?: D | undefined
  locale: string
  defaultLocale: string
  locales: string[]
}

推荐答案

很可能发生的情况是,GetStaticProps类型实际上是导致错误消息的原因:

它应该看起来像是:

type GetStaticProps = (context: GetStaticPropsContext) => void;

...然后是一个函数的getStaticProps变量赋值,该函数具有一些TS不喜欢的必需参数属性:您可以赋值一个更"允许"的函数(例如,一个接受可选参数的函数,一个更严格的函数,即接受必需参数的函数),但不能相反.

type GetStaticPropsContext<Q extends ParsedUrlQuery = ParsedUrlQuery, D extends PreviewData = PreviewData> = {
  params?: Q | undefined;
  preview?: boolean | undefined;
  previewData?: D | undefined;
  locale?: string | undefined;
  locales?: string[] | undefined;
  defaultLocale?: string | undefined;
}

type LocaleConfig = {
  locale: string
  defaultLocale: string
  locales: string[]
}

export const getStaticProps = (
  context: GetStaticPropsContext & LocaleConfig
) => { } // Okay

type GetStaticProps = (context: GetStaticPropsContext) => void

const getStaticProps2: GetStaticProps = getStaticProps;
// Type '(context: GetStaticPropsContext & LocaleConfig) => void' is not assignable to type 'GetStaticProps'.
// Type 'string | undefined' is not assignable to type 'string'.
// Type 'undefined' is not assignable to type 'string'.

Playground Link

通过说getStaticProps2函数是GetStaticProps类型,这意味着我们可以用空参数调用它(GetStaticPropsContext中的所有属性都是可选的):

getStaticProps2({});

但如果分配getStaticProps,一些属性将成为必需的……


至于转换类型以使它的一些可选属性成为必需的,确实,使用交叉点(&)是合适的技术.

您甚至可以使用RequiredPick实用程序类型的组合来捕获拼写错误并确保类型完全相同:

type LocaleConfig = Required<Pick<GetStaticPropsContext, "locale" | "defaultLocale" | "locales">>
//   ^? { locale: string; defaultLocale: string; locales: string []; }

export const getStaticProps = (
  context: GetStaticPropsContext & LocaleConfig
) => {
  // do stuff
  const locale = context.locale
  //    ^? string
  const preview = context.preview
  //    ^? boolean | undefined
}

getStaticProps({
  locale: "locale",
  defaultLocale: "",
  //locales: [] // Error if any of the Required properties is missing
});
// Property 'locales' is missing in type '{ locale: string; defaultLocale: string; }' but required in type 'Required<Pick<GetStaticPropsContext<ParsedUrlQuery, PreviewData>, "locale" | "defaultLocale" | "locales">>'.

Playground Link

Typescript相关问答推荐

有没有办法适当缩小类型?

如何使用属性作为具有Generics的TypScript类中的类型守护?

替代语法/逻辑以避免TS变量被分配之前使用." "

如何根据另一个属性的布尔值来缩小函数属性的返回类型?

在使用Typescribe时,是否有一种方法可以推断映射类型的键?

在TypeScrip中分配回调时,参数的分配方向与回调本身相反.为什么会这样呢?

如何使用泛型自动推断TS中的类型

具有泛型类型和缺省值的键

防止重复使用 Select 器重新渲染

(TypeScript)TypeError:无法读取未定义的属性(正在读取映射)"

如何过滤文字中的类对象联合类型?

如何获取受类型脚本泛型约束的有效输入参数

自动通用回调

打印脚本中正则函数和函数表达式的不同类型缩小行为

如何将通用接口的键正确设置为接口的键

VUE 3类型';字符串';不可分配给类型';参考<;字符串&>

如何使用angular15取消选中位于其他组件中的复选框

通过辅助函数获取嵌套属性时保留类型

在类型{}上找不到带有string类型参数的索引签名 - TypeScript

具有枚举泛型类型的 Typescript 对象数组