Skip to content

Commit 020e96b

Browse files
fix: add TsrSerializable (#5387)
1 parent e8052ce commit 020e96b

File tree

5 files changed

+99
-7
lines changed

5 files changed

+99
-7
lines changed

packages/router-core/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,6 +423,8 @@ export type {
423423
SerializableExtensions,
424424
DefaultSerializable,
425425
Serializable,
426+
TSR_SERIALIZABLE,
427+
TsrSerializable,
426428
} from './ssr/serializer/transformer'
427429

428430
export {

packages/router-core/src/ssr/serializer/transformer.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ import type {
99
import type { LooseReturnType } from '../../utils'
1010
import type { AnyRoute, ResolveAllSSR } from '../../route'
1111

12+
declare const TSR_SERIALIZABLE: unique symbol
13+
export type TSR_SERIALIZABLE = typeof TSR_SERIALIZABLE
14+
15+
export type TsrSerializable = { [TSR_SERIALIZABLE]: true }
1216
export interface DefaultSerializable {
1317
number: number
1418
string: string
@@ -17,6 +21,7 @@ export interface DefaultSerializable {
1721
undefined: undefined
1822
bigint: bigint
1923
Date: Date
24+
TsrSerializable: TsrSerializable
2025
}
2126

2227
export interface SerializableExtensions extends DefaultSerializable {}

packages/router-core/src/ssr/server.ts

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,3 @@ export {
88
transformReadableStreamWithRouter,
99
} from './transformStreamWithRouter'
1010
export { attachRouterServerSsrUtils, getOrigin } from './ssr-server'
11-
12-
// declare module '../router' {
13-
// export interface RegisterSsr {
14-
// ssr: true
15-
// }
16-
// }
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import { describe, expectTypeOf, it } from 'vitest'
2+
3+
import {
4+
Serializable,
5+
TsrSerializable,
6+
ValidateSerializable,
7+
ValidateSerializableResult,
8+
} from '../src/ssr/serializer/transformer'
9+
10+
describe('Serializer', () => {
11+
describe('Default types are serializable: $name', () => {
12+
it('string', () => {
13+
const value: string = 'hello'
14+
expectTypeOf<
15+
ValidateSerializableResult<typeof value, Serializable>
16+
>().toBeString()
17+
})
18+
it('number', () => {
19+
const value: number = 123
20+
21+
expectTypeOf<
22+
ValidateSerializableResult<typeof value, Serializable>
23+
>().toBeNumber()
24+
})
25+
it('boolean', () => {
26+
const value: boolean = true
27+
28+
expectTypeOf<
29+
ValidateSerializableResult<typeof value, Serializable>
30+
>().toBeBoolean()
31+
})
32+
it('null', () => {
33+
const value = null
34+
35+
expectTypeOf<
36+
ValidateSerializableResult<typeof value, Serializable>
37+
>().toBeNull()
38+
})
39+
it('undefined', () => {
40+
const value = undefined
41+
42+
expectTypeOf<
43+
ValidateSerializableResult<typeof value, Serializable>
44+
>().toBeUndefined()
45+
})
46+
it('bigint', () => {
47+
const value = BigInt(123)
48+
49+
expectTypeOf<
50+
ValidateSerializableResult<typeof value, Serializable>
51+
>().toBeBigInt()
52+
})
53+
it('Date', () => {
54+
const value = new Date()
55+
56+
expectTypeOf<
57+
ValidateSerializableResult<typeof value, Serializable>
58+
>().toEqualTypeOf<Date>()
59+
})
60+
})
61+
it('fails for non-serializable types', () => {
62+
const value = () => {}
63+
expectTypeOf<
64+
ValidateSerializable<typeof value, Serializable>
65+
>().toEqualTypeOf<'Function is not serializable'>()
66+
})
67+
68+
it('works for types extending TsrSerializable', () => {
69+
type MyCustomType = { f: () => {} } & TsrSerializable
70+
expectTypeOf<
71+
ValidateSerializable<MyCustomType, Serializable>
72+
>().toEqualTypeOf<MyCustomType>()
73+
})
74+
})

packages/start-client-core/src/tests/createServerFn.test-d.ts

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,12 @@ import { describe, expectTypeOf, test } from 'vitest'
22
import { createMiddleware } from '../createMiddleware'
33
import { createServerFn } from '../createServerFn'
44
import { TSS_SERVER_FUNCTION } from '../constants'
5-
import type { Constrain, Register, Validator } from '@tanstack/router-core'
5+
import type {
6+
Constrain,
7+
Register,
8+
TsrSerializable,
9+
Validator,
10+
} from '@tanstack/router-core'
611
import type { ConstrainValidator } from '../createServerFn'
712

813
test('createServerFn method with autocomplete', () => {
@@ -638,3 +643,15 @@ test('createServerFn returns sync array', () => {
638643

639644
expectTypeOf(serverFn()).toEqualTypeOf<Promise<Array<{ a: number }>>>()
640645
})
646+
647+
test('createServerFn respects TsrSerializable', () => {
648+
type MyCustomType = { f: () => void; value: string }
649+
type MyCustomTypeSerializable = MyCustomType & TsrSerializable
650+
const fn1 = createServerFn().handler(() => {
651+
const custom: MyCustomType = { f: () => {}, value: 'test' }
652+
return { nested: { custom: custom as MyCustomTypeSerializable } }
653+
})
654+
expectTypeOf(fn1()).toEqualTypeOf<
655+
Promise<{ nested: { custom: MyCustomTypeSerializable } }>
656+
>()
657+
})

0 commit comments

Comments
 (0)