Skip to content

Commit 4764ae5

Browse files
authored
feat: add null decoder (#205)
* feat: add null decoder * refactor: remove redundant rules/util * feat: add null encoder * chore: update changeset
1 parent df2364a commit 4764ae5

File tree

6 files changed

+55
-0
lines changed

6 files changed

+55
-0
lines changed

.changeset/wild-olives-exercise.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@tsplus/runtime": patch
3+
---
4+
5+
Add Encoder<null>, Guard<null> and Decoder<null>

packages/runtime/_src/Decoder.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,17 @@ export class DecoderErrorLiteral implements Decoder.Error {
132132
}
133133
}
134134

135+
export class DecoderErrorNull implements Decoder.Error {
136+
constructor(
137+
readonly value: unknown
138+
) {}
139+
render = () => {
140+
return Tree(
141+
`Expected null instead received one of type "${typeof this.value}"`
142+
)
143+
}
144+
}
145+
135146
export class DecoderErrorStructMissingField implements Decoder.Error {
136147
render = () => Tree(`Missing`)
137148
}
@@ -250,6 +261,15 @@ export const number: Decoder<number> = Decoder((u) =>
250261
Result.fail(new DecoderErrorPrimitive(u, "number"))
251262
)
252263

264+
/**
265+
* @tsplus implicit
266+
*/
267+
export const _null: Decoder<null> = Decoder((u) =>
268+
Derive<Guard<null>>().is(u) ?
269+
Result.success(u) :
270+
Result.fail(new DecoderErrorNull(u))
271+
)
272+
253273
/**
254274
* @tsplus implicit
255275
*/

packages/runtime/_src/Encoder.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,13 @@ export const boolean: Encoder<boolean> = Encoder((u) => u)
5252
*/
5353
export const number: Encoder<number> = Encoder((u) => u)
5454

55+
/**
56+
* Encoder for null
57+
*
58+
* @tsplus implicit
59+
*/
60+
export const _null: Encoder<null> = Encoder((u) => u)
61+
5562
/**
5663
* Encoder for a string
5764
*

packages/runtime/_src/Guard.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@ export const boolean: Guard<boolean> = Guard((u): u is boolean => typeof u === "
5656
*/
5757
export const number: Guard<number> = Guard((u): u is number => typeof u === "number")
5858

59+
/**
60+
* Guard for null
61+
*
62+
* @tsplus implicit
63+
*/
64+
export const _null: Guard<null> = Guard((u): u is null => u === null)
65+
5966
/**
6067
* Guard for a string
6168
*

packages/runtime/_test/Decoder.test.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,18 @@ describe.concurrent("Decoder", () => {
9292
`Expected literal "1" of type "number" instead received "200"`
9393
)
9494
})
95+
it("null", () => {
96+
const decoder: Decoder<null> = Derive()
97+
assert.deepEqual(decoder.decodeJSON(JSON.stringify(null)).right.value, null)
98+
assert.deepEqual(
99+
decoder.decodeJSON(JSON.stringify("no-hello")).left.value?.message,
100+
`Expected null instead received one of type "string"`
101+
)
102+
assert.deepEqual(
103+
decoder.decodeJSON(JSON.stringify(200)).left.value?.message,
104+
`Expected null instead received one of type "number"`
105+
)
106+
})
95107
it("struct", () => {
96108
interface Person {
97109
firstName: string

packages/runtime/_test/Encoder.test.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ describe.concurrent("Encoder", () => {
1212
const number: Encoder<number> = Derive()
1313
assert.deepEqual(number.encode(1), 1)
1414
})
15+
it("null", () => {
16+
const { encode }: Encoder<null> = Derive()
17+
assert.deepEqual(encode(null), null)
18+
})
1519
it("date", () => {
1620
const string: Encoder<Date> = Derive()
1721
const date = new Date()

0 commit comments

Comments
 (0)