Skip to content

Commit d1b14a1

Browse files
authored
Merge pull request #36516 from storybookjs/kasper/ts7-vitest-typecheck
2 parents 394025e + 3ce1646 commit d1b14a1

22 files changed

Lines changed: 588 additions & 336 deletions

‎.agents/guidelines/testing.md‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,11 @@ Use Vitest's global stubbing instead, which is tracked and restorable:
4747
- Never capture-and-restore by hand (`const original = globalThis.X; ... globalThis.X = original`); `vi.stubGlobal` + `vi.unstubAllGlobals()` does this correctly, including deleting keys that did not previously exist.
4848

4949
This applies to all ambient globals, not just `FEATURES` (e.g. `window`, `document`, `navigator`, `fetch`, `IS_REACT_ACT_ENVIRONMENT`).
50+
51+
## Type tests (`*.test-d.ts`)
52+
53+
Vitest type-checks `*.test-d.ts` files with the TypeScript 7 native compiler, the same one `yarn task check` uses. They are never executed at runtime.
54+
55+
- A package with type tests sets `test.typecheck.enabled: true` in its `vitest.config.ts`; the checker itself comes from `code/vitest.shared.ts`.
56+
- Run them from the repo root with `yarn vitest run --project <project> test-d`, where `<project>` is the config's `test.name` or else the package name (e.g. `core`, `@storybook/angular`).
57+
- Assert with `expectTypeOf` and use `// @ts-expect-error` for inputs that must be rejected; an unused directive fails the test.

‎AGENTS.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Storybook is a large TypeScript monorepo. The git root is the repo root, the mai
1616
- **Formatting**: oxfmt (root `.oxfmtrc.json`)
1717
- **CI environment**: Linux and Windows
1818
- **TS execution**: Migrating from `jiti` to native `node` for running `.ts` files. New scripts should use `node ./path/file.ts` with explicit `.ts` import extensions (enabled by `allowImportingTsExtensions` in tsconfig). Legacy scripts still use `jiti` but should be migrated over time.
19-
- **Type checking**: Per-package checks (`yarn task check`, `scripts/check/check-package.ts`) run on the TypeScript 7 native compiler (the `typescript-native` npm alias); diagnostics are filtered to the checked package. `@storybook/vue3`, `@storybook/docgen-harness` (for its `.vue` fixtures), and `@storybook/svelte` use `vue-tsc` / `svelte-check` (TS 6 based). The workspace `typescript` dependency stays on TS 6 for IDEs and API consumers, so tsconfigs must remain valid for both (e.g. no `baseUrl`).
19+
- **Type checking**: Per-package checks (`yarn task check`, `scripts/check/check-package.ts`) and Vitest type tests (`*.test-d.ts`) run on the TypeScript 7 native compiler (the `typescript-native` npm alias); check diagnostics are filtered to the checked package. `@storybook/vue3`, `@storybook/docgen-harness` (for its `.vue` fixtures), and `@storybook/svelte` use `vue-tsc` / `svelte-check` (TS 6 based). The workspace `typescript` dependency stays on TS 6 for IDEs and API consumers, so tsconfigs must remain valid for both (e.g. no `baseUrl`).
2020

2121
## Common Commands
2222

‎CONTRIBUTING.md‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,17 @@ You can use any version manager to install the correct version of Node.js. We re
5858

5959
3. If you're a Windows user, you'll need to enable Windows Subsystem for Linux (WSL). You can follow the instructions [here](https://docs.microsoft.com/en-us/windows/wsl/install).
6060

61+
### Editor setup
62+
63+
CI type-checks the monorepo with TypeScript 7 (`yarn task check` and the `*.test-d.ts` type tests). The workspace `typescript` package stays on TypeScript 6, because some tooling still needs its compiler API, so VS Code uses TypeScript 6 by default and can occasionally report different errors than CI.
64+
65+
To use the TypeScript 7 language server in VS Code instead (optional):
66+
67+
1. Install the [TypeScript 7 extension](https://marketplace.visualstudio.com/items?itemName=TypeScriptTeam.native-preview) (`TypeScriptTeam.native-preview`). When it first activates, it sets `"js/ts.experimental.useTsgo": true` in your user settings.
68+
2. Switch back and forth with the **TypeScript: Enable TypeScript 7 Language Server** and **TypeScript: Disable TypeScript 7 Language Server** commands.
69+
70+
The Vue and Svelte extensions still rely on TypeScript 6 plugins. While TypeScript 7 is on, TypeScript features inside `.vue` files and types of `.svelte` imports in `.ts` files are unavailable, so disable it when working on the Vue or Svelte packages.
71+
6172
### Running the local development environment
6273

6374
- All commands should be run in a terminal with administrator privileges in Windows environments.

‎code/core/vitest.config.ts‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ export default mergeConfig(
3131
name: 'core',
3232
typecheck: {
3333
enabled: true,
34-
ignoreSourceErrors: true,
3534
},
3635
server: {
3736
deps: {

‎code/frameworks/angular-vite/vitest.config.ts‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ export default mergeConfig(
99
test: {
1010
globals: true,
1111
setupFiles: ['src/test-setup.ts'],
12+
typecheck: {
13+
enabled: true,
14+
},
1215
},
1316
})
1417
);

‎code/frameworks/angular/vitest.config.ts‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ export default mergeConfig(
99
test: {
1010
globals: true,
1111
setupFiles: ['src/test-setup.ts'],
12+
typecheck: {
13+
enabled: true,
14+
},
1215
},
1316
})
1417
);

‎code/package.json‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@
105105
"esbuild-loader": "^4.3.0",
106106
"happy-dom": "^17.6.3",
107107
"http-server": "^14.1.1",
108-
"knip": "^5.70.2",
108+
"knip": "^6.38.0",
109109
"mock-require": "^3.0.3",
110110
"oxlint": "1.72.0",
111111
"prettier": "^3.7.1",
@@ -119,6 +119,7 @@
119119
"storybook-addon-pseudo-states": "workspace:*",
120120
"ts-dedent": "^2.0.0",
121121
"typescript": "^6.0.3",
122+
"typescript-native": "npm:typescript@^7.0.2",
122123
"uuid": "^11.1.0",
123124
"vite": "^7.0.4",
124125
"vite-plugin-inspect": "^11.0.0",

‎code/tsconfig.json‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
"customConditions": ["code"],
66
"esModuleInterop": true,
77
"forceConsistentCasingInFileNames": true,
8-
"ignoreDeprecations": "6.0",
98
"incremental": false,
109
"isolatedModules": true,
1110
"jsx": "preserve",

‎code/vitest.shared.ts‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
import { resolve } from 'node:path';
1+
import { createRequire } from 'node:module';
2+
import { dirname, join, resolve } from 'node:path';
23

34
import type { Plugin } from 'vite';
45
import { defineConfig } from 'vitest/config';
56

7+
const require = createRequire(import.meta.url);
8+
69
/**
710
* Loads .md/.html imports as text, matching the esbuild `loader` option in
811
* scripts/build/utils/generate-bundle.ts. Used by the MCP packages, which
@@ -26,5 +29,11 @@ export const vitestCommonConfig = defineConfig({
2629
globals: false,
2730
testTimeout: 10000,
2831
environment: 'node',
32+
// `enabled` is set per project with `*.test-d.ts` files: Vitest warns once per enabling project.
33+
typecheck: {
34+
checker: join(dirname(require.resolve('typescript-native/package.json')), 'bin', 'tsc'),
35+
// Diagnostics outside the type test files are `yarn task check`'s job.
36+
ignoreSourceErrors: true,
37+
},
2938
},
3039
});

‎scripts/build/build-package.ts‎

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,7 @@ import { buildEntries, hasPrebuild, isBuildEntries } from './entry-configs.ts';
2121
import { measure } from './utils/entry-utils.ts';
2222
import { generateBundle } from './utils/generate-bundle.ts';
2323
import { generatePackageJsonFile } from './utils/generate-package-json.ts';
24-
import { generateTypesFiles } from './utils/generate-types.ts';
25-
import { generateTypesFiles as generateTypesFilesRolldown } from './utils/generate-types-rolldown.ts';
24+
import { generateTypesFiles } from './utils/generate-types-rolldown.ts';
2625

2726
const {
2827
values: {
@@ -52,6 +51,11 @@ if (dtsResolver !== 'tsc' && dtsResolver !== 'oxc' && dtsResolver !== 'hybrid')
5251
}
5352
const resolvedDtsResolver: 'tsc' | 'oxc' | 'hybrid' = dtsResolver;
5453

54+
if (dtsBundler !== 'rolldown-tsgo' && dtsBundler !== 'rolldown') {
55+
throw new Error(`Invalid --dts-bundler: ${dtsBundler} (expected 'rolldown-tsgo' or 'rolldown')`);
56+
}
57+
const resolvedDtsBundler: 'rolldown-tsgo' | 'rolldown' = dtsBundler;
58+
5559
async function run() {
5660
const DIR_ROOT = join(import.meta.dirname, '..', '..');
5761
const DIR_CWD = cwd ? join(DIR_ROOT, cwd) : process.cwd();
@@ -99,24 +103,10 @@ async function run() {
99103
measure(async () => generateBundle({ cwd: DIR_CWD, entry, name, isWatch })),
100104
measure(async () => {
101105
if (isProduction) {
102-
switch (entry.dtsBundler ?? dtsBundler) {
103-
case 'rolldown':
104-
await generateTypesFilesRolldown(DIR_CWD, entry, {
105-
tsgo: false,
106-
resolver: resolvedDtsResolver,
107-
});
108-
break;
109-
case 'rolldown-tsgo':
110-
await generateTypesFilesRolldown(DIR_CWD, entry, {
111-
tsgo: true,
112-
resolver: resolvedDtsResolver,
113-
});
114-
break;
115-
case 'rollup':
116-
default:
117-
await generateTypesFiles(DIR_CWD, entry);
118-
break;
119-
}
106+
await generateTypesFiles(DIR_CWD, entry, {
107+
tsgo: (entry.dtsBundler ?? resolvedDtsBundler) === 'rolldown-tsgo',
108+
resolver: resolvedDtsResolver,
109+
});
120110
}
121111
}),
122112
]);

0 commit comments

Comments
 (0)