Skip to content

Commit

Permalink
chore (react-hooks): improve type of selector argument in useShape ho…
Browse files Browse the repository at this point in the history
…ok (#1610)

The default value for the `selector` argument used to be typed as
`never` which is wrong. This PR improves the type of the default value.
  • Loading branch information
kevin-dp authored Sep 3, 2024
1 parent 67b0a5e commit 0836ebb
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .changeset/lemon-eggs-care.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@electric-sql/react": patch
---

Improve type of selector argument in useShape hook.
8 changes: 5 additions & 3 deletions packages/react-hooks/src/react-hooks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export function getShape(shapeStream: ShapeStream): Shape {
}
}

interface UseShapeResult {
export interface UseShapeResult {
/**
* The array of rows that make up the Shape.
* @type {{ [key: string]: Value }[]}
Expand Down Expand Up @@ -91,14 +91,16 @@ function parseShapeData(shape: Shape): UseShapeResult {
}
}

const identity = (arg: unknown) => arg
function identity<T>(arg: T): T {
return arg
}

interface UseShapeOptions<Selection> extends ShapeStreamOptions {
selector?: (value: UseShapeResult) => Selection
}

export function useShape<Selection = UseShapeResult>({
selector = identity as never,
selector = identity as (arg: UseShapeResult) => Selection,
...options
}: UseShapeOptions<Selection>): Selection {
const shapeStream = getShapeStream(options as ShapeStreamOptions)
Expand Down
50 changes: 50 additions & 0 deletions packages/react-hooks/test/react-hooks.test-d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { describe, expectTypeOf, it } from 'vitest'
import { useShape, UseShapeResult } from '../src/react-hooks'

describe(`useShape`, () => {
it(`should infer correct return type when no selector is provided`, () => {
const shape = useShape({
url: ``,
})

expectTypeOf(shape).toEqualTypeOf<UseShapeResult>()
})

type SelectorRetType = {
foo: number
bar: boolean
baz: string
}

it(`should infer correct return type when a selector is provided`, () => {
const shape = useShape({
url: ``,
selector: (_value: UseShapeResult) => {
return {
foo: 5,
bar: true,
baz: `str`,
}
},
})

expectTypeOf(shape).toEqualTypeOf<SelectorRetType>()
})

it(`should raise a type error if type argument does not equal inferred return type`, () => {
const shape = useShape<number>({
url: ``,
// @ts-expect-error - should have type mismatch, because doesn't match the declared `Number` type
selector: (_value: UseShapeResult) => {
return {
foo: 5,
bar: true,
baz: `str`,
}
},
})

// Return type is based on the type argument
expectTypeOf(shape).toEqualTypeOf<number>()
})
})
1 change: 1 addition & 0 deletions packages/react-hooks/vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
globalSetup: `test/support/global-setup.ts`,
typecheck: { enabled: true },
},
})

0 comments on commit 0836ebb

Please sign in to comment.