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

docs: update TypeScript wildcard recommendations #9983

Merged
merged 1 commit into from
Feb 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -308,13 +308,6 @@ Using exports this way provides three major benefits:
- **More powerful features**: `exports` also has other powerful features compared to [the `main` field](https://nodejs.org/api/packages.html#main) like [Conditional Exports](https://nodejs.org/api/packages.html#conditional-exports). In general, we recommend using `exports` over `main` whenever possible as it is the more modern option.
- **IDE autocompletion**: By specifying the entrypoints for your package using `exports`, you can ensure that your code editor can provide auto-completion for the package's exports.

<Callout type="good-to-know">
You may also specify `exports` using a wildcard. However, you will lose some
IDE autocompletion due to performance tradeoffs with the TypeScript compiler.
For more information, visit [the TypeScript
guide](/repo/docs/guides/tools/typescript#package-entrypoint-wildcards).
</Callout>

#### `imports` (optional)

[The `imports` field](https://nodejs.org/api/packages.html#imports) gives you a way to create subpaths to other modules within your package. You can think of these like "shortcuts" to write simpler import paths that are more resilient to refactors that move files. To learn how, visit [the TypeScript page](/repo/docs/guides/tools/typescript#use-nodejs-subpath-imports-instead-of-typescript-compiler-paths).
Expand Down
61 changes: 21 additions & 40 deletions docs/repo-docs/guides/tools/typescript.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -60,22 +60,24 @@ Inside `packages/typescript-config`, you have a few `json` files which represent

```json title="./packages/typescript-config/base.json"
{
"compilerOptions": {
"esModuleInterop": true,
"skipLibCheck": true,
"target": "es2022",
"allowJs": true,
"resolveJsonModule": true,
"moduleDetection": "force",
"isolatedModules": true,
"strict": true,
"noUncheckedIndexedAccess": true,
"module": "NodeNext"
}
"compilerOptions": {
"esModuleInterop": true,
"skipLibCheck": true,
"target": "es2022",
"allowJs": true,
"resolveJsonModule": true,
"moduleDetection": "force",
"isolatedModules": true,
"strict": true,
"noUncheckedIndexedAccess": true,
"module": "NodeNext"
}
}
```

<LinkToDocumentation href="https://www.typescriptlang.org/tsconfig">`tsconfig` options reference</LinkToDocumentation>
<LinkToDocumentation href="https://www.typescriptlang.org/tsconfig">
`tsconfig` options reference
</LinkToDocumentation>

### Creating the rest of the package

Expand Down Expand Up @@ -159,13 +161,9 @@ Then, set up the entrypoints for your package in `package.json` so that other pa
```json title="./packages/ui/package.json"
{
"exports": {
"./button": {
"types": "./src/button.ts"
"default": "./dist/button.js",
},
"./input": {
"types": "./src/input.ts"
"default": "./dist/input.js",
"./*": {
"types": "./src/*.ts"
"default": "./dist/*.js",
}
}
}
Expand All @@ -175,7 +173,7 @@ Setting up `exports` this way has several advantages:

- Using the `types` field allows `tsserver` to use the code in `src` as the source of truth for your code's types. Your editor will always be up-to-date with the latest interfaces from your code.
- You can quickly add new entrypoints to your package without creating [dangerous barrel files](https://vercel.com/blog/how-we-optimized-package-imports-in-next-js#what's-the-problem-with-barrel-files).
- You'll receive auto-importing suggestions for your imports across package boundaries in your editor. For more information about why you may not want to wildcard the entrypoints, see the [limitations section](#package-entrypoint-wildcards).
- You'll receive auto-importing suggestions for your imports across package boundaries in your editor.

<Callout type="warn">
If you're publishing the package, you cannot use references to source code in
Expand Down Expand Up @@ -226,7 +224,7 @@ For [Internal Packages](/repo/docs/core-concepts/internal-packages), we recommen

#### Just-in-Time Packages

Exports from [Just-in-Time Packages](/repo/docs/core-concepts/internal-packages#just-in-time-packages) will automatically bring you to the original TypeScript source code as long as you aren't using [entrypoint wildcards](#package-entrypoint-wildcards). Go-to-definition will work as expected.
Exports from [Just-in-Time Packages](/repo/docs/core-concepts/internal-packages#just-in-time-packages) will automatically bring you to the original TypeScript source code. Go-to-definition will work as expected.

#### Compiled Packages

Expand Down Expand Up @@ -296,7 +294,7 @@ In [Compiled packages](https://turbo.build/repo/docs/core-concepts/internal-pack
<Tab value="Source code">

```tsx title="./packages/ui/button.tsx"
import { MY_STRING } from "#utils.js"; // Uses .js extension // [!code highlight]
import { MY_STRING } from '#utils.js'; // Uses .js extension // [!code highlight]

export const Button = () => {
return <button>{MY_STRING}</button>;
Expand Down Expand Up @@ -326,20 +324,3 @@ We don't recommend using TypeScript Project References as they introduce both an
`tsserver` is not able to use different TypeScript versions for different packages in your code editor. Instead, it will discover a specific version and use that everywhere.

This can result in differences between the linting errors that show in your editor and when you run `tsc` scripts to check types. If this is an issue for you, consider [keeping the TypeScript dependency on the same version](/repo/docs/crafting-your-repository/managing-dependencies#keeping-dependencies-on-the-same-version).

### Package entrypoint wildcards

We recommend [listing the entrypoints to your package explicitly](/repo/docs/guides/tools/typescript#creating-entrypoints-to-the-package) - but, to some, this feels too verbose. Instead, you can use wildcards to capture entrypoints:

```json title="./packages/ui/package.json"
{
"exports": {
"./*": {
"types": "./src/*.ts",
"default": "./dist/*.js"
}
}
}
```

While this will work, it comes with the tradeoff of not being able to auto-import across package boundaries [due to performance reasons with the TypeScript compiler](https://github.com/microsoft/TypeScript/issues/53116#issuecomment-1458887175). This tradeoff may or may not be worth it to you depending on your use case.
2 changes: 1 addition & 1 deletion examples/basic/apps/docs/next-env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
/// <reference types="next/image-types/global" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
2 changes: 1 addition & 1 deletion examples/basic/apps/web/next-env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
/// <reference types="next/image-types/global" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
4 changes: 1 addition & 3 deletions examples/basic/packages/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
"version": "0.0.0",
"private": true,
"exports": {
"./button": "./src/button.tsx",
"./card": "./src/card.tsx",
"./code": "./src/code.tsx"
"./*": "./src/*.tsx"
},
"scripts": {
"lint": "eslint . --max-warnings 0",
Expand Down
2 changes: 1 addition & 1 deletion examples/with-tailwind/packages/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
],
"exports": {
"./styles.css": "./dist/index.css",
"./card": "./src/card.tsx"
"./*": "./src/*.tsx"
},
"license": "MIT",
"scripts": {
Expand Down
Loading