无法导入生成的类型文件 create-react-app
Can't import generated typings file create-react-app
这是我第一次创建 typescript react npm 模块,我正在尝试在我的项目中导入一个使用新 npm 模块的类型定义。 VSCode 智能感知能够找到并建议自动生成的 .d.ts
文件之一,但应用程序无法加载它。怎么回事?
./src/components/MyPage.tsx
Module not found: Can't resolve '@myorg/component-library/build/Input/Input.types' in '/Users/jbaczuk/path/to/project/src/components'
如果我将导入路径更改为 '@myorg/component-library/build/Input/Input.types.d'
,它会抛出:
./node_modules/@myorg/component-library/build/Input/Input.types.d.ts 2:7
Module parse failed: Unexpected token (2:7)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
> export declare enum Type {
| text = "text",
| number = "number"
Input.types.d.ts
export declare enum Type {
text = "text",
number = "number"
}
export interface InputProps {
type?: Type;
}
//# sourceMappingURL=Input.types.d.ts.map
MyPage.ts
import React from 'react';
import { Type } from '@myorg/component-library/build/Input/Input.types.d';
export default function MyPage(): JSX.Element {
{/** ... more stuff **/}}
return (
{/** ... more stuff **/}}
<Input
onChangeValue={onChangeText}
type={Type.text}
/>
{/** ... more stuff **/}}
)
package.json
{
"name": "my-project",
"version": "0.1.0",
"description": "My Project",
"private": true,
"repository": "git@github.com:MyOrg/MyProject.git",
"license": "UNLICENSED",
"dependencies": {
"@myorg/component-library": "../../component-library",
"axios": "^0.21.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-router-dom": "^5.2.0",
"react-scripts": "4.0.3",
"styled-components": "^5.2.1",
"web-vitals": "^1.0.1"
},
"scripts": {
"build:tailwind": "tailwind build src/tailwind.css -o src/tailwind.output.css",
"watch:tailwind": "chokidar 'src/**/*.css' 'src/**/*.scss' --ignore src/tailwind.output.css -c 'npm run build:tailwind'",
"start": "npm-run-all build:tailwind --parallel watch:tailwind start:react",
"start:react": "PORT=3002 react-scripts start",
"prebuild": "run-s build:tailwind",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"lint": "eslint '*/**/*.{js,ts,tsx}' --quiet --fix",
"check-types": "tsc"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"@tailwindcss/postcss7-compat": "^2.0.4",
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
"@types/jest": "^26.0.15",
"@types/node": "^12.0.0",
"@types/react": "^17.0.0",
"@types/react-dom": "^17.0.0",
"@types/react-router-dom": "^5.1.7",
"@types/testing-library__jest-dom": "^5.9.5",
"@types/testing-library__react": "^10.2.0",
"@typescript-eslint/eslint-plugin": "^4.14.2",
"@typescript-eslint/parser": "^4.14.2",
"autoprefixer": "^9",
"chokidar-cli": "^2.1.0",
"eslint": "^7.19.0",
"eslint-config-prettier": "^7.2.0",
"eslint-plugin-prettier": "^3.3.1",
"eslint-plugin-react": "^7.22.0",
"eslint-plugin-react-hooks": "^4.2.0",
"husky": "^4.3.8",
"lint-staged": ">=10",
"npm-run-all": "^4.1.5",
"postcss": "^7",
"prettier": "^2.2.1",
"react-scripts": "4.0.2",
"tailwindcss": "npm:@tailwindcss/postcss7-compat",
"ts-jest": "^26.5.0",
"typescript": "^4.1.2"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.{js,ts,tsx}": [
"eslint --fix"
]
}
}
tsconfig.json
{
"compilerOptions": {
"target": "ES2020",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"module": "esnext",
"allowJs": true,
"jsx": "react-jsx",
"outDir": "./build",
"noEmit": true,
"isolatedModules": true,
"strict": true,
"noFallthroughCasesInSwitch": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"types": [
"node",
"jest"
],
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": [
"src"
],
"exclude": [
"build"
]
}
组件库
package.json
{
"name": "@myorg/component-library",
"repository": {
"type": "git",
"url": "https://github.com/myOrg/ComponentLibrary.git"
},
"version": "0.2.1",
"description": "MyOrg react component library",
"main": "build/index.js",
"module": "build/index.esm.js",
"files": [
"build"
],
"types": "build/index.d.ts",
"scripts": {
"build": "rm -rf build && rollup -c --environment NODE_ENV:production",
"test": "jest",
"test:watch": "jest --watch",
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --fix --ext .ts",
"storybook": "start-storybook -p 6006",
"storybook:export": "build-storybook",
"prepublishOnly": "npm run build",
"create": "node ./util/create"
},
"author": "Jordan Baczuk",
"license": "UNLICENSED",
"devDependencies": {
"@babel/core": "^7.13.14",
"@rollup/plugin-commonjs": "^18.0.0",
"@rollup/plugin-node-resolve": "^11.2.1",
"@storybook/addon-essentials": "^6.2.2",
"@storybook/addons": "^6.2.2",
"@storybook/react": "^6.2.2",
"@tailwindcss/postcss7-compat": "^2.0.4",
"@testing-library/jest-dom": "^5.11.10",
"@testing-library/react": "^11.2.6",
"@testing-library/user-event": "^13.1.1",
"@types/jest": "^26.0.22",
"@types/react": "^17.0.3",
"@typescript-eslint/eslint-plugin": "^4.14.0",
"@typescript-eslint/parser": "^4.14.0",
"autoprefixer": "^9",
"babel-loader": "^8.2.2",
"babel-preset-react-app": "^10.0.0",
"eslint": "^7.18.0",
"eslint-config-prettier": "^7.2.0",
"eslint-plugin-prettier": "^3.3.1",
"eslint-plugin-react": "^7.22.0",
"eslint-plugin-react-hooks": "^4.2.0",
"husky": "^4.3.8",
"identity-obj-proxy": "^3.0.0",
"jest": "^26.6.3",
"lint-staged": ">=10",
"postcss": "^7",
"prettier": "^2.2.1",
"rollup": "^2.44.0",
"rollup-plugin-peer-deps-external": "^2.2.4",
"rollup-plugin-postcss": "3.1.8",
"rollup-plugin-typescript2": "^0.30.0",
"tailwindcss": "npm:@tailwindcss/postcss7-compat",
"ts-jest": "^26.5.4",
"typescript": "^4.2.3"
},
"peerDependencies": {
"react": "^17.0.2",
"react-dom": "^17.0.2"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged && npm test"
}
},
"lint-staged": {
"*.{js,ts,tsx}": [
"eslint --fix"
],
"*.js": "eslint --cache --fix"
},
"dependencies": {
"@fontsource/titillium-web": "^4.2.2",
"@heroicons/react": "^1.0.0",
"react-tooltip": "^4.2.17"
}
}
tsconfig.js
{
"compilerOptions": {
"declarationMap": true,
"declaration": true,
"declarationDir": "build",
"module": "esnext",
"target": "es5",
"lib": ["es6", "dom", "es2016", "es2017"],
"sourceMap": true,
"jsx": "react",
"moduleResolution": "node",
"allowSyntheticDefaultImports": true,
"esModuleInterop": true
},
"include": ["src/**/*"],
"exclude": [
"node_modules",
"build",
"src/**/*.stories.tsx",
"src/**/*.spec.ts",
"src/**/*.tests.tsx"
]
}
rollup.config.js
import peerDepsExternal from 'rollup-plugin-peer-deps-external'
import resolve from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs'
import typescript from 'rollup-plugin-typescript2'
import packageJson from './package.json'
import postcss from 'rollup-plugin-postcss'
export default {
input: 'src/index.ts',
output: [
{
file: packageJson.main,
format: 'cjs',
sourcemap: true
},
{
file: packageJson.module,
format: 'esm',
sourcemap: true
}
],
external: ['styled-components'],
plugins: [
peerDepsExternal(),
postcss({
minimize: true,
modules: true,
use: {
sass: null,
stylus: null,
less: { javascriptEnabled: true }
},
extract: true
}),
resolve(),
commonjs(),
typescript()
]
}
我有点惊讶您直接从 types.d 文件加载类型并使用构建路径!我希望 import { Type } from '@myorg/component-library
.
那是因为在为打字稿创作的 npm 库创建 package.json 的过程中,您将定义一个主 属性 指向导出所有 Javascript 属性的地方和一个类型 属性 指向导出你想要的打字稿类型的地方。
如果那个主要入口点(因为你的构建过程)实际上是 build/index.js
并且相应的类型文件是 build/index.d.ts
那么你在导入时永远不会直接引用构建文件夹或文件 -指向正确的路径由捆绑过程处理。
看看主流(但简单)的打字稿 npm 模块,如 https://github.com/jamiebuilds/unstated-next/blob/master/package.json ( https://www.npmjs.com/package/unstated-next )
您可以看到主要 属性 指向应该导出 javascript 名称的文件 https://github.com/jamiebuilds/unstated-next/blob/master/package.json#L6 and the types property pointing to the file which should export the types https://github.com/jamiebuilds/unstated-next/blob/master/package.json#L9 and these happen to be in the 'dist' folder but this is never referenced when importing it as per the docs at https://www.npmjs.com/package/unstated-next
我终于开始工作了,并且学到了一些东西。
- 枚举不是类型。
enum is not a type which means that it generates js code not like types and interfaces. https://github.com/ng-packagr/ng-packagr/issues/809#issuecomment-385187297
- 为了从 npm 模块导出枚举,您必须从主模块文件中显式导出它:
MyPackage/src/index.ts
import Card from './Card/Card'
import Input from './Input/Input'
import Form from './Form/Form'
import Link from './Link/Link'
import Text from './Text/Text'
import Button from './Button/Button'
import { HeroIcons } from './style/heroicons'
export { Card, Input, Form, Link, Text, Button, HeroIcons }
export * from './Input/Input.types'
现在我可以像这样导入它了:
import { Type } from '@myorg/component-library';
这是我第一次创建 typescript react npm 模块,我正在尝试在我的项目中导入一个使用新 npm 模块的类型定义。 VSCode 智能感知能够找到并建议自动生成的 .d.ts
文件之一,但应用程序无法加载它。怎么回事?
./src/components/MyPage.tsx
Module not found: Can't resolve '@myorg/component-library/build/Input/Input.types' in '/Users/jbaczuk/path/to/project/src/components'
如果我将导入路径更改为 '@myorg/component-library/build/Input/Input.types.d'
,它会抛出:
./node_modules/@myorg/component-library/build/Input/Input.types.d.ts 2:7
Module parse failed: Unexpected token (2:7)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
> export declare enum Type {
| text = "text",
| number = "number"
Input.types.d.ts
export declare enum Type {
text = "text",
number = "number"
}
export interface InputProps {
type?: Type;
}
//# sourceMappingURL=Input.types.d.ts.map
MyPage.ts
import React from 'react';
import { Type } from '@myorg/component-library/build/Input/Input.types.d';
export default function MyPage(): JSX.Element {
{/** ... more stuff **/}}
return (
{/** ... more stuff **/}}
<Input
onChangeValue={onChangeText}
type={Type.text}
/>
{/** ... more stuff **/}}
)
package.json
{
"name": "my-project",
"version": "0.1.0",
"description": "My Project",
"private": true,
"repository": "git@github.com:MyOrg/MyProject.git",
"license": "UNLICENSED",
"dependencies": {
"@myorg/component-library": "../../component-library",
"axios": "^0.21.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-router-dom": "^5.2.0",
"react-scripts": "4.0.3",
"styled-components": "^5.2.1",
"web-vitals": "^1.0.1"
},
"scripts": {
"build:tailwind": "tailwind build src/tailwind.css -o src/tailwind.output.css",
"watch:tailwind": "chokidar 'src/**/*.css' 'src/**/*.scss' --ignore src/tailwind.output.css -c 'npm run build:tailwind'",
"start": "npm-run-all build:tailwind --parallel watch:tailwind start:react",
"start:react": "PORT=3002 react-scripts start",
"prebuild": "run-s build:tailwind",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"lint": "eslint '*/**/*.{js,ts,tsx}' --quiet --fix",
"check-types": "tsc"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"@tailwindcss/postcss7-compat": "^2.0.4",
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.1.0",
"@testing-library/user-event": "^12.1.10",
"@types/jest": "^26.0.15",
"@types/node": "^12.0.0",
"@types/react": "^17.0.0",
"@types/react-dom": "^17.0.0",
"@types/react-router-dom": "^5.1.7",
"@types/testing-library__jest-dom": "^5.9.5",
"@types/testing-library__react": "^10.2.0",
"@typescript-eslint/eslint-plugin": "^4.14.2",
"@typescript-eslint/parser": "^4.14.2",
"autoprefixer": "^9",
"chokidar-cli": "^2.1.0",
"eslint": "^7.19.0",
"eslint-config-prettier": "^7.2.0",
"eslint-plugin-prettier": "^3.3.1",
"eslint-plugin-react": "^7.22.0",
"eslint-plugin-react-hooks": "^4.2.0",
"husky": "^4.3.8",
"lint-staged": ">=10",
"npm-run-all": "^4.1.5",
"postcss": "^7",
"prettier": "^2.2.1",
"react-scripts": "4.0.2",
"tailwindcss": "npm:@tailwindcss/postcss7-compat",
"ts-jest": "^26.5.0",
"typescript": "^4.1.2"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.{js,ts,tsx}": [
"eslint --fix"
]
}
}
tsconfig.json
{
"compilerOptions": {
"target": "ES2020",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"module": "esnext",
"allowJs": true,
"jsx": "react-jsx",
"outDir": "./build",
"noEmit": true,
"isolatedModules": true,
"strict": true,
"noFallthroughCasesInSwitch": true,
"moduleResolution": "node",
"resolveJsonModule": true,
"types": [
"node",
"jest"
],
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": [
"src"
],
"exclude": [
"build"
]
}
组件库
package.json
{
"name": "@myorg/component-library",
"repository": {
"type": "git",
"url": "https://github.com/myOrg/ComponentLibrary.git"
},
"version": "0.2.1",
"description": "MyOrg react component library",
"main": "build/index.js",
"module": "build/index.esm.js",
"files": [
"build"
],
"types": "build/index.d.ts",
"scripts": {
"build": "rm -rf build && rollup -c --environment NODE_ENV:production",
"test": "jest",
"test:watch": "jest --watch",
"lint": "eslint . --ext .ts",
"lint:fix": "eslint . --fix --ext .ts",
"storybook": "start-storybook -p 6006",
"storybook:export": "build-storybook",
"prepublishOnly": "npm run build",
"create": "node ./util/create"
},
"author": "Jordan Baczuk",
"license": "UNLICENSED",
"devDependencies": {
"@babel/core": "^7.13.14",
"@rollup/plugin-commonjs": "^18.0.0",
"@rollup/plugin-node-resolve": "^11.2.1",
"@storybook/addon-essentials": "^6.2.2",
"@storybook/addons": "^6.2.2",
"@storybook/react": "^6.2.2",
"@tailwindcss/postcss7-compat": "^2.0.4",
"@testing-library/jest-dom": "^5.11.10",
"@testing-library/react": "^11.2.6",
"@testing-library/user-event": "^13.1.1",
"@types/jest": "^26.0.22",
"@types/react": "^17.0.3",
"@typescript-eslint/eslint-plugin": "^4.14.0",
"@typescript-eslint/parser": "^4.14.0",
"autoprefixer": "^9",
"babel-loader": "^8.2.2",
"babel-preset-react-app": "^10.0.0",
"eslint": "^7.18.0",
"eslint-config-prettier": "^7.2.0",
"eslint-plugin-prettier": "^3.3.1",
"eslint-plugin-react": "^7.22.0",
"eslint-plugin-react-hooks": "^4.2.0",
"husky": "^4.3.8",
"identity-obj-proxy": "^3.0.0",
"jest": "^26.6.3",
"lint-staged": ">=10",
"postcss": "^7",
"prettier": "^2.2.1",
"rollup": "^2.44.0",
"rollup-plugin-peer-deps-external": "^2.2.4",
"rollup-plugin-postcss": "3.1.8",
"rollup-plugin-typescript2": "^0.30.0",
"tailwindcss": "npm:@tailwindcss/postcss7-compat",
"ts-jest": "^26.5.4",
"typescript": "^4.2.3"
},
"peerDependencies": {
"react": "^17.0.2",
"react-dom": "^17.0.2"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged && npm test"
}
},
"lint-staged": {
"*.{js,ts,tsx}": [
"eslint --fix"
],
"*.js": "eslint --cache --fix"
},
"dependencies": {
"@fontsource/titillium-web": "^4.2.2",
"@heroicons/react": "^1.0.0",
"react-tooltip": "^4.2.17"
}
}
tsconfig.js
{
"compilerOptions": {
"declarationMap": true,
"declaration": true,
"declarationDir": "build",
"module": "esnext",
"target": "es5",
"lib": ["es6", "dom", "es2016", "es2017"],
"sourceMap": true,
"jsx": "react",
"moduleResolution": "node",
"allowSyntheticDefaultImports": true,
"esModuleInterop": true
},
"include": ["src/**/*"],
"exclude": [
"node_modules",
"build",
"src/**/*.stories.tsx",
"src/**/*.spec.ts",
"src/**/*.tests.tsx"
]
}
rollup.config.js
import peerDepsExternal from 'rollup-plugin-peer-deps-external'
import resolve from '@rollup/plugin-node-resolve'
import commonjs from '@rollup/plugin-commonjs'
import typescript from 'rollup-plugin-typescript2'
import packageJson from './package.json'
import postcss from 'rollup-plugin-postcss'
export default {
input: 'src/index.ts',
output: [
{
file: packageJson.main,
format: 'cjs',
sourcemap: true
},
{
file: packageJson.module,
format: 'esm',
sourcemap: true
}
],
external: ['styled-components'],
plugins: [
peerDepsExternal(),
postcss({
minimize: true,
modules: true,
use: {
sass: null,
stylus: null,
less: { javascriptEnabled: true }
},
extract: true
}),
resolve(),
commonjs(),
typescript()
]
}
我有点惊讶您直接从 types.d 文件加载类型并使用构建路径!我希望 import { Type } from '@myorg/component-library
.
那是因为在为打字稿创作的 npm 库创建 package.json 的过程中,您将定义一个主 属性 指向导出所有 Javascript 属性的地方和一个类型 属性 指向导出你想要的打字稿类型的地方。
如果那个主要入口点(因为你的构建过程)实际上是 build/index.js
并且相应的类型文件是 build/index.d.ts
那么你在导入时永远不会直接引用构建文件夹或文件 -指向正确的路径由捆绑过程处理。
看看主流(但简单)的打字稿 npm 模块,如 https://github.com/jamiebuilds/unstated-next/blob/master/package.json ( https://www.npmjs.com/package/unstated-next )
您可以看到主要 属性 指向应该导出 javascript 名称的文件 https://github.com/jamiebuilds/unstated-next/blob/master/package.json#L6 and the types property pointing to the file which should export the types https://github.com/jamiebuilds/unstated-next/blob/master/package.json#L9 and these happen to be in the 'dist' folder but this is never referenced when importing it as per the docs at https://www.npmjs.com/package/unstated-next
我终于开始工作了,并且学到了一些东西。
- 枚举不是类型。
enum is not a type which means that it generates js code not like types and interfaces. https://github.com/ng-packagr/ng-packagr/issues/809#issuecomment-385187297
- 为了从 npm 模块导出枚举,您必须从主模块文件中显式导出它:
MyPackage/src/index.ts
import Card from './Card/Card'
import Input from './Input/Input'
import Form from './Form/Form'
import Link from './Link/Link'
import Text from './Text/Text'
import Button from './Button/Button'
import { HeroIcons } from './style/heroicons'
export { Card, Input, Form, Link, Text, Button, HeroIcons }
export * from './Input/Input.types'
现在我可以像这样导入它了:
import { Type } from '@myorg/component-library';