-
Notifications
You must be signed in to change notification settings - Fork 149
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat:
Message
type guard helpers (#1572)
Addresses #1453 Adds the type guards to check whether a message is a `ControlMessage` or a `ChangeMessage`, documented, tested, and exported. I've also honed in on the message type definitions a bit more as I had experienced an uncaught bug due to the generality of the `Headers` type.
- Loading branch information
Showing
13 changed files
with
186 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@electric-sql/client": patch | ||
--- | ||
|
||
Add `Message` type guard helpers `isChangeMessage` and `isControlMessage`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import { ChangeMessage, ControlMessage, Message, Value } from './types' | ||
|
||
/** | ||
* Type guard for checking {@link Message} is {@link ChangeMessage}. | ||
* | ||
* See [TS docs](https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards) | ||
* for information on how to use type guards. | ||
* | ||
* @param message - the message to check | ||
* @returns true if the message is a {@link ChangeMessage} | ||
* | ||
* @example | ||
* ```ts | ||
* if (isChangeMessage(message)) { | ||
* const msgChng: ChangeMessage = message // Ok | ||
* const msgCtrl: ControlMessage = message // Err, type mismatch | ||
* } | ||
* ``` | ||
*/ | ||
export function isChangeMessage<T extends Value = { [key: string]: Value }>( | ||
message: Message<T> | ||
): message is ChangeMessage<T> { | ||
return `key` in message | ||
} | ||
|
||
/** | ||
* Type guard for checking {@link Message} is {@link ControlMessage}. | ||
* | ||
* See [TS docs](https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards) | ||
* for information on how to use type guards. | ||
* | ||
* @param message - the message to check | ||
* @returns true if the message is a {@link ControlMessage} | ||
* | ||
* * @example | ||
* ```ts | ||
* if (isControlMessage(message)) { | ||
* const msgChng: ChangeMessage = message // Err, type mismatch | ||
* const msgCtrl: ControlMessage = message // Ok | ||
* } | ||
* ``` | ||
*/ | ||
export function isControlMessage<T extends Value = { [key: string]: Value }>( | ||
message: Message<T> | ||
): message is ControlMessage { | ||
return !isChangeMessage(message) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
export * from './client' | ||
export * from './types' | ||
export * from './helpers' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import { describe, expectTypeOf, it } from 'vitest' | ||
import { | ||
ChangeMessage, | ||
ControlMessage, | ||
isChangeMessage, | ||
isControlMessage, | ||
Message, | ||
} from '../src' | ||
|
||
describe(`helpers`, () => { | ||
it(`should respect ChangeMessages type guard`, () => { | ||
const message = { | ||
headers: { | ||
operation: `insert`, | ||
}, | ||
offset: `-1`, | ||
key: `foo`, | ||
value: { foo: `bar` }, | ||
} as Message<{ foo: string }> | ||
|
||
if (isChangeMessage(message)) { | ||
const msgChng: ChangeMessage<{ foo: string }> = message | ||
expectTypeOf(msgChng).toEqualTypeOf<ChangeMessage<{ foo: string }>>() | ||
|
||
// @ts-expect-error - should have type mismatch | ||
message as ControlMessage | ||
} | ||
}) | ||
|
||
it(`should respect ControlMessages type guard`, () => { | ||
const message = { | ||
headers: { | ||
control: `up-to-date`, | ||
}, | ||
} as Message<{ [key: string]: string }> | ||
|
||
if (isControlMessage(message)) { | ||
const msgCtrl: ControlMessage = message | ||
expectTypeOf(msgCtrl).toEqualTypeOf<ControlMessage>() | ||
|
||
// @ts-expect-error - should have type mismatch | ||
message as ChangeMessage<{ foo: string }> | ||
} | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { describe, expect, it } from 'vitest' | ||
import { isChangeMessage, isControlMessage, Message } from '../src' | ||
|
||
describe(`helpers`, () => { | ||
it(`should correctly detect ChangeMessages`, () => { | ||
const message = { | ||
headers: { | ||
operation: `insert`, | ||
}, | ||
offset: `-1`, | ||
key: `key`, | ||
value: { key: `value` }, | ||
} as Message | ||
|
||
expect(isChangeMessage(message)).toBe(true) | ||
expect(isControlMessage(message)).toBe(false) | ||
}) | ||
|
||
it(`should correctly detect ControlMessages`, () => { | ||
const message = { | ||
headers: { | ||
control: `up-to-date`, | ||
}, | ||
} as Message | ||
expect(isControlMessage(message)).toBe(true) | ||
expect(isChangeMessage(message)).toBe(false) | ||
}) | ||
}) |
Oops, something went wrong.