如何覆盖 Next.js `*.svg` 模块声明?

brc*_*-dd 10 typescript reactjs next.js nextjs-image

Next.js 最近进行了修改(在 v11.0.x 中),其类型定义如下:

next-env.d.ts(不可修改,在每次构建时重新生成):

/// <reference types="next" />
/// <reference types="next/types/global" />
/// <reference types="next/image-types/global" />
Run Code Online (Sandbox Code Playgroud)

node_modules/next/image-types/global.d.ts(不可修改,不想使用patch-package)中:

declare module '*.svg' {
  const content: any
  export default content
}
Run Code Online (Sandbox Code Playgroud)

现在的问题是我正在使用@svgr/webpack,因此我需要执行以下操作:

declare module '*.svg' {
  const content: React.FC<React.SVGAttributes<SVGElement>>
  export default content
}
Run Code Online (Sandbox Code Playgroud)

之前将此代码放置在index.d.ts用于工作的资产文件夹中。但现在不行了,结果我被迫单独投射每个导入。有什么办法可以直接做到这一点吗?

brc*_*-dd 9

我正在使用以下解决方法:

  • 添加next-env.d.ts以排除数组tsconfig.json

    {
      // ...
      "exclude": ["node_modules", "next-env.d.ts"]
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 添加/ 。next-env.d.ts.gitignore.eslintignore

  • 创建新文件custom.d.ts

    /// <reference types="next" />
    /// <reference types="next/types/global" />
    
    // additional things that one used to put here before Next.js v11
    
    Run Code Online (Sandbox Code Playgroud)
  • 创建新文件images.d.ts

    type StaticImageData = {
      src: string;
      height: number;
      width: number;
      placeholder?: string;
    };
    
    declare module '*.png' {
      const content: StaticImageData;
      export default content;
    }
    
    declare module '*.svg' {
      const content: React.FC<React.SVGProps<SVGSVGElement>>;
      export default content;
    }
    
    declare module '*.jpg' {
      const content: StaticImageData;
      export default content;
    }
    
    declare module '*.jpeg' {
      const content: StaticImageData;
      export default content;
    }
    
    declare module '*.gif' {
      const content: StaticImageData;
      export default content;
    }
    
    declare module '*.webp' {
      const content: StaticImageData;
      export default content;
    }
    
    declare module '*.ico' {
      const content: StaticImageData;
      export default content;
    }
    
    declare module '*.bmp' {
      const content: StaticImageData;
      export default content;
    }
    
    Run Code Online (Sandbox Code Playgroud)
  • 确保这些文件按照include.array中指定的模式进行处理tsconfig

  • *.avif如果您在以下位置使用它们,请添加声明next@12

    declare module '*.avif' {
      const content: StaticImageData
      export default content
    }
    
    Run Code Online (Sandbox Code Playgroud)


Lau*_*nce 9

替换的替代方法next-env.d.ts是添加额外的声明文件,例如,如https://nextjs.org/docs/basic-features/typescriptadditional.d.ts中所述。

正如文档中所述,此文件必须包含在文件include的数组中tsconfig.json,但我发现顺序也很重要 - 附加文件必须包含 next-env.d.ts.

这似乎是因为当包含默认导出的同一模块有多个声明时,第一个声明获胜。

// additional.d.ts
declare module "*.svg" {
  import React from "react";

  const content: React.FunctionComponent<React.SVGProps<SVGSVGElement>>;

  export default content;
}
Run Code Online (Sandbox Code Playgroud)
// tsconfig.json
{
  "include": ["additional.d.ts", "next-env.d.ts"] // The order matters!
}
Run Code Online (Sandbox Code Playgroud)

这给出了我们首选的 SVG 类型,同时保留了next-env.d.ts.

这似乎比简单地替换内置类型文件更可取,因为 Next 团队保留了将来调整类型的权利,这意味着复制的类型需要手动保持最新,而这种方法不似乎是一种记录在案的方法。