Skip to content

Commit fddaeb8

Browse files
authored
[backport] fix: remove satisfies keyword from type validation to preserve old TS compatibility (#83071)
1 parent 497ec6a commit fddaeb8

File tree

2 files changed

+12
-7
lines changed

2 files changed

+12
-7
lines changed

packages/next/src/server/lib/router-utils/typegen.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,10 +446,13 @@ export function generateValidatorFile(
446446
: type
447447
return `// Validate ${filePath}
448448
{
449+
type __IsExpected<Specific extends ${typeWithRoute}> = Specific
449450
const handler = {} as typeof import(${JSON.stringify(
450451
importPath.replace(/\.tsx?$/, '.js')
451452
)})
452-
handler satisfies ${typeWithRoute}
453+
type __Check = __IsExpected<typeof handler>
454+
// @ts-ignore
455+
type __Unused = __Check
453456
}`
454457
})
455458
.join('\n\n')

test/e2e/app-dir/typed-routes-validator/typed-routes-validator.test.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ describe('typed-routes-validator', () => {
1313
it('should generate route validation correctly', async () => {
1414
const dts = await next.readFile('.next/types/validator.ts')
1515
// sanity check that dev generation is working
16-
expect(dts).toContain('handler satisfies AppPageConfig')
16+
expect(dts).toContain('const handler = {} as typeof import(')
1717
})
1818

1919
if (isNextStart) {
@@ -51,7 +51,7 @@ describe('typed-routes-validator', () => {
5151

5252
expect(exitCode).toBe(1)
5353
expect(cliOutput).toMatch(
54-
/Type error: Type 'typeof import\(.*\)' does not satisfy the expected type 'AppPageConfig<"\/invalid">'/
54+
/Type error: Type 'typeof import\(.*' does not satisfy the constraint 'AppPageConfig</
5555
)
5656
})
5757

@@ -111,7 +111,7 @@ describe('typed-routes-validator', () => {
111111

112112
expect(exitCode).toBe(1)
113113
expect(cliOutput).toMatch(
114-
/Type error: Type 'typeof import.*does not satisfy the expected type 'RouteHandlerConfig<"\/invalid">'/
114+
/Type error: Type 'typeof import\(.*' does not satisfy the constraint 'RouteHandlerConfig</
115115
)
116116
})
117117

@@ -132,7 +132,9 @@ describe('typed-routes-validator', () => {
132132
await next.deleteFile('app/invalid-2/route.ts')
133133

134134
expect(exitCode).toBe(1)
135-
expect(cliOutput).toContain(`Types of property 'POST' are incompatible.`)
135+
expect(cliOutput).toMatch(
136+
/Type error: Type 'typeof import\(.*' does not satisfy the constraint 'RouteHandlerConfig</
137+
)
136138
})
137139

138140
it('should pass type checking with valid layout exports', async () => {
@@ -174,7 +176,7 @@ describe('typed-routes-validator', () => {
174176

175177
expect(exitCode).toBe(1)
176178
expect(cliOutput).toMatch(
177-
/Type error: Type 'typeof import\(.*does not satisfy the expected type 'LayoutConfig<"\/invalid">'/
179+
/Type error: Type 'typeof import\(.*' does not satisfy the constraint 'LayoutConfig</
178180
)
179181
})
180182

@@ -220,7 +222,7 @@ describe('typed-routes-validator', () => {
220222

221223
expect(exitCode).toBe(1)
222224
expect(cliOutput).toMatch(
223-
/Type error: Type 'typeof import\(.*does not satisfy the expected type 'ApiRouteConfig'/
225+
/Type error: Type 'typeof import\(.*' does not satisfy the constraint 'ApiRouteConfig'/
224226
)
225227
})
226228
}

0 commit comments

Comments
 (0)