Skip to content

Commit

Permalink
docs: update TypeScript wildcard recommendations (#9983)
Browse files Browse the repository at this point in the history
### Description

@thdxr kindly pointed out that the wildcard recommendations in our docs
weren't matching what he was seeing in his editor. I investigated and am
similarly seeing that wildcard recommendations work as one would hope.
The last time that I tried this, there was some limit at 10 exports
paths or 10 variable exports (my memory is fuzzy). But that appears to
be removed now in latest versions of TypeScript with modern settings
(which is what the Turborepo docs on other tools always assume).

Additional credit to @baptisteArno who also was pointing this out to me
in #9827. I'm going to use this PR since it has a few more spots in docs
where things are updated, and has additional updates to our examples.
But let the record show that @baptisteArno deserves credits here!

### Testing

I hand-tested this in my editor and here's what I see. One or more of
these didn't used to work but now it does.

![CleanShot 2025-02-15 at 23 32
38@2x](https://github.com/user-attachments/assets/ac7a44b3-8fe3-4a72-a580-2abb151d2100)

Additionally, here is my editor recommending 10+ entrypoints.
![CleanShot 2025-02-15 at 23 35
19@2x](https://github.com/user-attachments/assets/695087e4-5e29-474a-b573-cadd62e14fab)
  • Loading branch information
anthonyshew authored Feb 18, 2025
1 parent 24f7329 commit 3dfb1d3
Show file tree
Hide file tree
Showing 6 changed files with 25 additions and 53 deletions.
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

0 comments on commit 3dfb1d3

Please sign in to comment.