Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Module resolution: default import does not work with type: module #57743

Closed
mohd-akram opened this issue Mar 12, 2024 · 9 comments
Closed

Module resolution: default import does not work with type: module #57743

mohd-akram opened this issue Mar 12, 2024 · 9 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@mohd-akram
Copy link

mohd-akram commented Mar 12, 2024

Demo Repo

https://github.com/mohd-akram/ts-next-repro

Which of the following problems are you reporting?

The module specifier resolves at runtime, but not at build time

Demonstrate the defect described above with a code sample.

import Head from 'next/head.js';
<Head><title>Hello</title></Head>;

Run tsc --showConfig and paste its output here

{
    "compilerOptions": {
        "module": "node16",
        "jsx": "preserve",
        "target": "es2022",
        "moduleResolution": "node16",
        "moduleDetection": "force",
        "esModuleInterop": true,
        "allowSyntheticDefaultImports": true,
        "useDefineForClassFields": true
    },
    "files": [
        "./index.tsx"
    ]
}

Run tsc --traceResolution and paste its output here

Too long to paste.

Paste the package.json of the importing module, if it exists

{
  "main": "index.js",
  "type": "module",
  "scripts": {
    "build": "tsc"
  },
  "devDependencies": {
    "@types/react": "^18.2.65",
    "typescript": "^5.4.2"
  },
  "dependencies": {
    "next": "^14.1.3"
  }
}

Paste the package.json of the target module, if it exists

{
  "name": "next",
  "version": "14.1.3",
  "description": "The React Framework",
  "main": "./dist/server/next.js",
  "license": "MIT",
  "repository": "vercel/next.js",
  "bugs": "https://github.com/vercel/next.js/issues",
  "homepage": "https://nextjs.org",
  "types": "index.d.ts",
  "files": [
    "dist",
    "app.js",
    "app.d.ts",
    "babel.js",
    "babel.d.ts",
    "client.js",
    "client.d.ts",
    "compat",
    "cache.js",
    "cache.d.ts",
    "config.js",
    "config.d.ts",
    "constants.js",
    "constants.d.ts",
    "document.js",
    "document.d.ts",
    "dynamic.js",
    "dynamic.d.ts",
    "error.js",
    "error.d.ts",
    "future",
    "legacy",
    "script.js",
    "script.d.ts",
    "server.js",
    "server.d.ts",
    "head.js",
    "head.d.ts",
    "image.js",
    "image.d.ts",
    "link.js",
    "link.d.ts",
    "router.js",
    "router.d.ts",
    "jest.js",
    "jest.d.ts",
    "amp.js",
    "amp.d.ts",
    "og.js",
    "og.d.ts",
    "index.d.ts",
    "types/index.d.ts",
    "types/global.d.ts",
    "types/compiled.d.ts",
    "image-types/global.d.ts",
    "navigation-types/navigation.d.ts",
    "navigation-types/compat/navigation.d.ts",
    "font",
    "navigation.js",
    "navigation.d.ts",
    "headers.js",
    "headers.d.ts",
    "navigation-types",
    "web-vitals.js",
    "web-vitals.d.ts",
    "experimental/testmode/playwright.js",
    "experimental/testmode/playwright.d.ts",
    "experimental/testmode/playwright/msw.js",
    "experimental/testmode/playwright/msw.d.ts",
    "experimental/testmode/proxy.js",
    "experimental/testmode/proxy.d.ts"
  ],
  "bin": {
    "next": "./dist/bin/next"
  },
  "scripts": {
    "dev": "taskr",
    "release": "taskr release",
    "build": "pnpm release",
    "prepublishOnly": "cd ../../ && turbo run build",
    "types": "tsc --declaration --emitDeclarationOnly --stripInternal --declarationDir dist",
    "typescript": "tsec --noEmit",
    "ncc-compiled": "ncc cache clean && taskr ncc"
  },
  "taskr": {
    "requires": [
      "./taskfile-webpack.js",
      "./taskfile-ncc.js",
      "./taskfile-swc.js",
      "./taskfile-watch.js"
    ]
  },
  "dependencies": {
    "@next/env": "14.1.3",
    "@swc/helpers": "0.5.2",
    "busboy": "1.6.0",
    "caniuse-lite": "^1.0.30001579",
    "graceful-fs": "^4.2.11",
    "postcss": "8.4.31",
    "styled-jsx": "5.1.1"
  },
  "peerDependencies": {
    "@opentelemetry/api": "^1.1.0",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "sass": "^1.3.0"
  },
  "peerDependenciesMeta": {
    "sass": {
      "optional": true
    },
    "@opentelemetry/api": {
      "optional": true
    }
  },
  "devDependencies": {
    "@ampproject/toolbox-optimizer": "2.8.3",
    "@babel/code-frame": "7.22.5",
    "@babel/core": "7.22.5",
    "@babel/eslint-parser": "7.22.5",
    "@babel/generator": "7.22.5",
    "@babel/plugin-proposal-class-properties": "7.18.6",
    "@babel/plugin-proposal-export-namespace-from": "7.18.9",
    "@babel/plugin-proposal-numeric-separator": "7.18.6",
    "@babel/plugin-proposal-object-rest-spread": "7.20.7",
    "@babel/plugin-syntax-bigint": "7.8.3",
    "@babel/plugin-syntax-dynamic-import": "7.8.3",
    "@babel/plugin-syntax-import-assertions": "7.22.5",
    "@babel/plugin-syntax-jsx": "7.22.5",
    "@babel/plugin-transform-modules-commonjs": "7.22.5",
    "@babel/plugin-transform-runtime": "7.22.5",
    "@babel/preset-env": "7.22.5",
    "@babel/preset-react": "7.22.5",
    "@babel/preset-typescript": "7.22.5",
    "@babel/runtime": "7.22.5",
    "@babel/traverse": "7.22.5",
    "@babel/types": "7.22.5",
    "@capsizecss/metrics": "1.1.0",
    "@edge-runtime/cookies": "4.1.0",
    "@edge-runtime/ponyfill": "2.4.2",
    "@edge-runtime/primitives": "4.1.0",
    "@hapi/accept": "5.0.2",
    "@jest/transform": "29.5.0",
    "@jest/types": "29.5.0",
    "@mswjs/interceptors": "0.23.0",
    "@napi-rs/cli": "2.16.2",
    "@napi-rs/triples": "1.1.0",
    "@next/polyfill-module": "14.1.3",
    "@next/polyfill-nomodule": "14.1.3",
    "@next/react-dev-overlay": "14.1.3",
    "@next/react-refresh-utils": "14.1.3",
    "@next/swc": "14.1.3",
    "@opentelemetry/api": "1.6.0",
    "@playwright/test": "^1.35.1",
    "@taskr/clear": "1.1.0",
    "@taskr/esnext": "1.1.0",
    "@types/amphtml-validator": "1.0.0",
    "@types/babel__code-frame": "7.0.2",
    "@types/babel__core": "7.1.12",
    "@types/babel__generator": "7.6.2",
    "@types/babel__template": "7.4.0",
    "@types/babel__traverse": "7.11.0",
    "@types/bytes": "3.1.1",
    "@types/ci-info": "2.0.0",
    "@types/compression": "0.0.36",
    "@types/content-disposition": "0.5.4",
    "@types/content-type": "1.1.3",
    "@types/cookie": "0.3.3",
    "@types/cross-spawn": "6.0.0",
    "@types/debug": "4.1.5",
    "@types/express-serve-static-core": "4.17.33",
    "@types/fresh": "0.5.0",
    "@types/glob": "7.1.1",
    "@types/graceful-fs": "4.1.9",
    "@types/jsonwebtoken": "9.0.0",
    "@types/lodash": "4.14.198",
    "@types/lodash.curry": "4.1.6",
    "@types/lru-cache": "5.1.0",
    "@types/micromatch": "4.0.2",
    "@types/path-to-regexp": "1.7.0",
    "@types/platform": "1.3.4",
    "@types/react": "18.2.37",
    "@types/react-dom": "18.2.15",
    "@types/react-is": "17.0.3",
    "@types/semver": "7.3.1",
    "@types/send": "0.14.4",
    "@types/shell-quote": "1.7.1",
    "@types/tar": "6.1.5",
    "@types/text-table": "0.2.1",
    "@types/ua-parser-js": "0.7.36",
    "@types/uuid": "8.3.1",
    "@types/webpack-sources1": "npm:@types/webpack-sources@0.1.5",
    "@types/ws": "8.2.0",
    "@vercel/ncc": "0.34.0",
    "@vercel/nft": "0.26.2",
    "@vercel/turbopack-ecmascript-runtime": "https://gitpkg-fork.vercel.sh/vercel/turbo/crates/turbopack-ecmascript-runtime/js?turbopack-240117.3",
    "acorn": "8.5.0",
    "amphtml-validator": "1.0.35",
    "anser": "1.4.9",
    "arg": "4.1.0",
    "assert": "2.0.0",
    "async-retry": "1.2.3",
    "async-sema": "3.0.0",
    "babel-plugin-transform-define": "2.0.0",
    "babel-plugin-transform-react-remove-prop-types": "0.4.24",
    "browserify-zlib": "0.2.0",
    "browserslist": "4.22.2",
    "buffer": "5.6.0",
    "bytes": "3.1.1",
    "ci-info": "watson/ci-info#f43f6a1cefff47fb361c88cf4b943fdbcaafe540",
    "cli-select": "1.1.2",
    "client-only": "0.0.1",
    "comment-json": "3.0.3",
    "compression": "1.7.4",
    "conf": "5.0.0",
    "constants-browserify": "1.0.0",
    "content-disposition": "0.5.3",
    "content-type": "1.0.4",
    "cookie": "0.4.1",
    "cross-spawn": "7.0.3",
    "crypto-browserify": "3.12.0",
    "css.escape": "1.5.1",
    "cssnano-preset-default": "5.2.14",
    "data-uri-to-buffer": "3.0.1",
    "debug": "4.1.1",
    "devalue": "2.0.1",
    "domain-browser": "4.19.0",
    "edge-runtime": "2.5.4",
    "events": "3.3.0",
    "find-up": "4.1.0",
    "fresh": "0.5.2",
    "get-orientation": "1.1.2",
    "glob": "7.1.7",
    "gzip-size": "5.1.1",
    "http-proxy": "1.18.1",
    "http-proxy-agent": "5.0.0",
    "https-browserify": "1.0.0",
    "https-proxy-agent": "5.0.1",
    "icss-utils": "5.1.0",
    "ignore-loader": "0.1.2",
    "image-size": "1.0.0",
    "is-docker": "2.0.0",
    "is-wsl": "2.2.0",
    "jest-worker": "27.5.1",
    "json5": "2.2.3",
    "jsonwebtoken": "9.0.0",
    "loader-runner": "4.3.0",
    "loader-utils2": "npm:loader-utils@2.0.0",
    "loader-utils3": "npm:loader-utils@3.1.3",
    "lodash.curry": "4.1.1",
    "lru-cache": "5.1.1",
    "micromatch": "4.0.4",
    "mini-css-extract-plugin": "2.4.3",
    "msw": "1.3.0",
    "nanoid": "3.1.32",
    "native-url": "0.3.4",
    "neo-async": "2.6.1",
    "node-html-parser": "5.3.3",
    "ora": "4.0.4",
    "os-browserify": "0.3.0",
    "p-limit": "3.1.0",
    "path-browserify": "1.0.1",
    "path-to-regexp": "6.1.0",
    "platform": "1.3.6",
    "postcss-flexbugs-fixes": "5.0.2",
    "postcss-modules-extract-imports": "3.0.0",
    "postcss-modules-local-by-default": "4.0.0",
    "postcss-modules-scope": "3.0.0",
    "postcss-modules-values": "4.0.0",
    "postcss-preset-env": "7.4.3",
    "postcss-safe-parser": "6.0.0",
    "postcss-scss": "4.0.3",
    "postcss-value-parser": "4.2.0",
    "process": "0.11.10",
    "punycode": "2.1.1",
    "querystring-es3": "0.2.1",
    "raw-body": "2.4.1",
    "react-is": "18.2.0",
    "react-refresh": "0.12.0",
    "regenerator-runtime": "0.13.4",
    "sass-loader": "12.4.0",
    "schema-utils2": "npm:schema-utils@2.7.1",
    "schema-utils3": "npm:schema-utils@3.0.0",
    "semver": "7.3.2",
    "send": "0.17.1",
    "server-only": "0.0.1",
    "setimmediate": "1.0.5",
    "shell-quote": "1.7.3",
    "source-map": "0.6.1",
    "stacktrace-parser": "0.1.10",
    "stream-browserify": "3.0.0",
    "stream-http": "3.1.1",
    "strict-event-emitter": "0.5.0",
    "string-hash": "1.1.3",
    "string_decoder": "1.3.0",
    "strip-ansi": "6.0.0",
    "superstruct": "1.0.3",
    "tar": "6.1.15",
    "taskr": "1.1.0",
    "terser": "5.14.1",
    "terser-webpack-plugin": "5.3.9",
    "text-table": "0.2.0",
    "timers-browserify": "2.0.12",
    "tty-browserify": "0.0.1",
    "ua-parser-js": "1.0.35",
    "unistore": "3.4.1",
    "util": "0.12.4",
    "uuid": "8.3.2",
    "vm-browserify": "1.1.2",
    "watchpack": "2.4.0",
    "web-vitals": "3.0.0",
    "webpack": "5.86.0",
    "webpack-sources1": "npm:webpack-sources@1.4.3",
    "webpack-sources3": "npm:webpack-sources@3.2.3",
    "ws": "8.2.3",
    "zod": "3.22.3"
  },
  "engines": {
    "node": ">=18.17.0"
  },
  "optionalDependencies": {
    "@next/swc-darwin-arm64": "14.1.3",
    "@next/swc-darwin-x64": "14.1.3",
    "@next/swc-linux-arm64-gnu": "14.1.3",
    "@next/swc-linux-arm64-musl": "14.1.3",
    "@next/swc-linux-x64-gnu": "14.1.3",
    "@next/swc-linux-x64-musl": "14.1.3",
    "@next/swc-win32-arm64-msvc": "14.1.3",
    "@next/swc-win32-ia32-msvc": "14.1.3",
    "@next/swc-win32-x64-msvc": "14.1.3"
  }
}

Any other comments can go here

Next types:

next/head.d.ts:

import Head from './dist/shared/lib/head'
export * from './dist/shared/lib/head'
export default Head

next/dist/shared/lib/head.d.ts:

import React from 'react';
export declare function defaultHead(inAmpMode?: boolean): JSX.Element[];
/**
 * This component injects elements to `<head>` of your page.
 * To avoid duplicated `tags` in `<head>` you can use the `key` property, which will make sure every tag is only rendered once.
 */
declare function Head({ children }: {
    children: React.ReactNode;
}): import("react/jsx-runtime").JSX.Element;
export default Head;
@RyanCavanaugh RyanCavanaugh added the Working as Intended The behavior described is the intended behavior; this is not a bug label Mar 12, 2024
@RyanCavanaugh
Copy link
Member

next is inferred to be a CommonJS module because it doesn't have type: "module" in its package.json and doesn't have any other indication that it can be loaded as an ESM module.

See #50058 (comment)

@mohd-akram
Copy link
Author

I don't fully understand that comment. Next does a default export and I do a default import. It seems simple enough that this should work? Why is the type of next considered when that information is already specified in declaration files via either export = or export default?

@RyanCavanaugh
Copy link
Member

The comment explains all of this

@mohd-akram
Copy link
Author

mohd-akram commented Mar 12, 2024

It doesn't address why TypeScript considers type of an imported module rather than simply accepting what module authors specify in their type files. For distinguishing between the export default example and the MyFunction one in your comment, the library author can use export default and export = respectively. This is how it already works in non-Node16 modes.

@RyanCavanaugh
Copy link
Member

If you write your exports in ESM syntax, but the package itself is CJS (which it is), then Node16 module mode says to respect what the package says, because that's what Node does.

@fatcerberus
Copy link

For the record:
https://arethetypeswrong.github.io/?p=next%4014.1.3

@mohd-akram
Copy link
Author

@RyanCavanaugh I think that's a mistake. The exports are eventually transformed into ESM imports according to Node.js. Per Node.js, that transformation uses static analysis and its outcome is unknown beforehand. Accepting what the types say lets those who do know - the library authors - inform TypeScript of the final shape of the library.

@RyanCavanaugh
Copy link
Member

What you're describing - that package authors tell TS how their package works - is what's happening, it just happens that next is telling TS the wrong thing.

@typescript-bot
Copy link
Collaborator

This issue has been marked as "Working as Intended" and has seen no recent activity. It has been automatically closed for house-keeping purposes.

@typescript-bot typescript-bot closed this as not planned Won't fix, can't repro, duplicate, stale Mar 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

4 participants