无法在打字稿中导入 svg 文件

Posted

技术标签:

【中文标题】无法在打字稿中导入 svg 文件【英文标题】:Unable to import svg files in typescript 【发布时间】:2022-01-20 08:59:52 【问题描述】:

typescript(*.tsx) 文件中,我无法使用以下语句导入 svg 文件:

import logo from './logo.svg';

转译器说:[ts] cannot find module './logo.svg'. 我的 svg 文件只是 <svg>...</svg>

但是在.js 文件中,我可以使用完全相同的导入语句导入它而不会出现任何问题。我想这与 svg 文件的类型有关,必须以某种方式为 ts 转译器设置。

您能分享一下如何在 ts 文件中进行这项工作吗?

【问题讨论】:

svg 文件不是 javascript,不能像 javascript 模块那样使用。您应该改为使用 http 请求加载这些文件。 你在使用 Webpack 吗?这是我见过的唯一能理解这种import 声明的东西。也许 Webpack 是在你的 JavaScript 中允许这样做的,但它在 TypeScript 文件中并没有发挥同样的魔力。 (我不认为 TypeScript 本身知道在这里做什么。) 如果你使用 Webpack,你可能需要分享你的 Webpack 配置以获得更多帮助。 阅读更多内容,您可以使用const logo = require("./logo.svg"); 或直接忽略错误。 (我相信 TS 仍然应该输出正确的代码。) 为什么,为什么 Webpack/React 必须使事情复杂化?用import 导入任何东西不是更简单吗?对于像我这样的新手,这些事情让我很沮丧。我们不是在 2020 年,“自动配置”应该成为常态吗? 【参考方案1】:

对我来说,以上解决方案都不能单独工作。因为我在当前项目中没有使用 Webpack。

我调查了日志中的输出,然后以下方式对我有用,无需创建文件 (custom.d.ts)、更改配置或安装新依赖项:

const logo: string = require("../assets/images/logo.svg").default;

<img src=logo  />

【讨论】:

【参考方案2】:

在 CRA 应用中导入 SVG 文件

如果您想在 CRA 应用程序 (create-react-app) 中导入 SVG 文件,无需进行任何配置,您可以使用以下方法之一:

方法一

import  ReactComponent as MyIcon  from "./assets/images/my-icon.svg";
...
<MyIcon />

方法二

import myIconFileName from './assets/images/my-icon.svg';
...    
<img src=myIconFileName />

【讨论】:

是的,这种方法显然适用于 js 文件,但不适用于 ts(x) 文件!问题是在“TypeScrip”中导入 svg 文件。【参考方案3】:

如果你使用webpack,安装svg-inline-loader,在webpack.config.js中添加模块:


    test: /\.svg$/,
    loader: 'svg-inline-loader',

编译后效果很好。

如果您的 IDE 报告交互错误,可以通过添加 //@ts-ignore 来解决:

//@ts-ignore
import logo from './logo.svg';

svg-inline-loader webpack docs

【讨论】:

【参考方案4】: 如果您使用的是create-react-app 2+:docs

添加一个具有正确类型的custom.d.ts 文件(我在我的src 目录的根路径上创建)(感谢RedMatt):

declare module '*.svg' 
  const content: React.FunctionComponent<React.SVGAttributes<SVGElement>>;
  export default content;

安装svg-react-loader或一些other,然后:

将其用作主要的 svg 加载器 或者,如果您正在迁移代码库并且不想接触工作部分 (JS),请在导入时指定加载程序:
import MySVG from '-!svg-react-loader!src/assets/images/name.svg'

那就把它当做 JSX 标签使用吧:

function f()  
  return (<MySVG />); 

【讨论】:

ESLint:意外的'!'在“-!svg-react-loader!src/assets/svg/bg.svg”中。不要使用 import 语法来配置 webpack 加载器。(import/no-webpack-loader-syntax)【参考方案5】:

希望!这将对某人有所帮助。

实际上,我尝试了所有步骤,但我们必须了解一件事,您必须将 custom.d.ts 文件创建到相应的 SVG 导入文件夹中。

ts 配置文件


  "compilerOptions": 
    "target": "ES6",
    "jsx": "react",
    "module": "ESNext",
    "moduleResolution": "Node",
    "baseUrl": "./",
    "paths": 
      "@components/*": ["src/components/*"],
      "@styles/*": ["src/styles/*"],
      "@static/*": ["src/static/*"]
    ,
    "allowJs": true,
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true,
    "isolatedModules": true
  ,
  "include": ["src/**/*", "src/static/optional.d.ts"],
  "exclude": ["node_modules", "build"]


可选的.d.ts

declare module '*.svg' 
    import * as React from 'react';

    export const ReactComponent: React.FunctionComponent<React.SVGProps<
        SVGSVGElement
    > &  title?: string >;

    const src: string;
    export default src;

终于通用的导出文件了:

import Logo from './images/logo.svg';
import BellDot from './images/bell-dot.svg';
import Logout from './images/logout.svg';
import pageNotFound from './images/page-not-found.png';

export 
    Logo,
    BellDot,
    pageNotFound,
    Logout

为了更好的想法:

【讨论】:

【参考方案6】:

如果您使用的是 Create-React-App 启动器,请确保 react-app-env.d.ts 包含以下行:

/// <reference types="react-scripts" />

【讨论】:

这对我有用。还有一点我想指出,最直接的方法是将 create-react-app 与 typescript 模板一起使用,该模板为您配置项目并开箱即用地使用 svgs。【参考方案7】:

你可以像create-react-app一样为svgs声明模块:

react-app.d.ts

declare module '*.svg' 
  import * as React from 'react';

  export const ReactComponent: React.FunctionComponent<React.SVGProps<
    SVGSVGElement
  > &  title?: string >;

  const src: string;
  export default src;

见source

【讨论】:

我不明白。为什么它定义 export const ReactComponent 然后使用 export default src ?不应该是export default ReactComponent吗? 因为 CRA 在后台使用 SVGR 加载程序,它就是这样做的:npmjs.com/package/@svgr/webpack 另见 github.com/gregberge/svgr/issues/546【参考方案8】:

如果你使用 webpack,你可以通过创建自定义类型文件来做到这一点。

创建一个名为 custom.d.ts 的文件,其内容如下:

declare module "*.svg" 
  const content: any;
  export default content;

custom.d.ts 添加到tsconfig.json 如下

"include": ["src/components", "src/custom.d.ts"]

来源:https://webpack.js.org/guides/typescript/#importing-other-assets

【讨论】:

您可能需要将其添加到 tsconfig.jsoninclude 部分。 谢谢!我知道它必须包含在某个地方,但我无法想象在哪里。即使我认为它在 tsconfig.json 中,但我不知道该怎么做。感谢您的评论。我搜索了一下,发现:"files": [ "custom.d.ts" ] 您可以通过输入以下内容对 JSX 组件进行类型检查:const content: React.FunctionComponent&lt;React.SVGAttributes&lt;SVGElement&gt;&gt;; 是否可以让custom.d.ts 文件在全局范围内工作,以便SVG 可以位于与custom.d.ts 文件不同的目录中?我得到一个错误“找不到模块”,除非它在同一个目录中。 这不会在 Angular 中导入文件的内容,而是将文件名作为字符串导入。我需要内容。我们如何获取文件的内容?【参考方案9】:

要将 non-code assets 与 TypeScript 一起使用,我们需要延迟这些 imports 的类型。这需要一个 custom.d.ts 文件,该文件表示我们项目中 TypeScript 的自定义定义。

让我们为 .svg 文件设置一个声明:

custom.d.ts

declare module "*.svg" 
  const content: any;
  export default content;

在这里,我们通过指定任何以 .svg 结尾的导入并将模块的内容定义为 any,从而为 SVG 声明一个新模块。

【讨论】:

【参考方案10】:
    // eslint-disable-next-line spaced-comment
/// <reference types="react-scripts" />

如果您使用的是 puglin slint,可能是因为他已禁用认为这是评论但不阅读 svg 您需要此类型脚本模块只需禁用该行并开心

【讨论】:

【参考方案11】:

我找到的解决方案:在 ReactJS 项目中,在文件 react-app-env.d.ts 中,您只需删除注释中的空格,例如:

之前

// / <reference types="react-scripts" />

之后

/// <reference types="react-scripts" />

希望能帮到你

【讨论】:

对于使用 create-react-app 并配置了 eslint 的人来说,这样可以解决问题 我没有找到任何解释,但就我而言,它似乎有效。任何想法为什么? 这里解释了它的作用:***.com/questions/60628874/…【参考方案12】:

我在尝试 REACT + typescript 教程时遇到了同样的问题。 对我有用的是以下导入语句。

import * as logo from 'logo.svg'

这是我在 package.json 中的依赖项。

  "dependencies": 
    "react": "^16.8.4",
    "react-dom": "^16.8.4",
    "react-scripts-ts": "3.1.0"
  ,

希望对某人有所帮助。

【讨论】:

【参考方案13】:

我们已经实现了另一种方法:制作您的 SVG 组件。我这样做是因为它让我感到困扰,我在 imports 旁边使用 commonJS require 语句。

【讨论】:

【参考方案14】:

感谢smarx 指出使用require()。所以在我的情况下应该是:

const logo = require("./logo.svg") as string;

在 *.tsx 文件中运行良好

【讨论】:

logo 最好命名为 logoPath,因为它就是这样。 @DharmaTurtle 我认为这可以讨论。此外,它在问题中称为logo,因此它是对这个特定问题的更好答案。 @DharmaTurtle 老实说,变量的名称是无关紧要的,为什么要分心这么琐碎的事情? 我喜欢这个答案而不是创建自定义配置规则。唯一的问题是,如果有任何副作用,这在生产构建中的效果如何? 无法完成这项工作——请澄清一下? ***.com/questions/65205211/…

以上是关于无法在打字稿中导入 svg 文件的主要内容,如果未能解决你的问题,请参考以下文章

如何在打字稿中导入js文件作为模块

无法在 TypeScript 中导入 Google Storage

在打字稿中导入 javascript 库时出错

为啥 vscode 从打字稿缓存中导入包

json 尝试在打字稿中导入外部模块

如何在打字稿monorepo中导入本地包