Skip to content

Commit

Permalink
fix(types): add undefined for initial values
Browse files Browse the repository at this point in the history
  • Loading branch information
posva committed Nov 28, 2022
1 parent 098c16c commit 76e1527
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 22 deletions.
12 changes: 10 additions & 2 deletions src/database/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,15 +190,23 @@ export function useList<T = unknown>(
}) as _RefDatabase<VueDatabaseQueryData<T>>
}

/**
* Creates a reactive variable connected to the database as an object. If the reference is a primitive, it will be
* converted to an object containing a `$value` property with the primitive value and an `id` property with the
* reference's key.
*
* @param reference - Reference or query to the database
* @param options - optional options
*/
export function useObject<T = unknown>(
reference: _MaybeRef<DatabaseReference>,
options?: UseObjectOptions
): _RefDatabase<VueDatabaseDocumentData<T> | undefined> {
const data = ref<T>() as Ref<T | undefined>
const data = ref<T | null>()
return _useDatabaseRef(reference, {
target: data,
...options,
}) as _RefDatabase<VueDatabaseDocumentData<T> | undefined>
}) as _RefDatabase<VueDatabaseDocumentData<T>>
}

export const unbind = (target: Ref, reset?: ResetOption) =>
Expand Down
8 changes: 3 additions & 5 deletions src/firestore/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ export function useDocument<
>(
documentRef: _MaybeRef<_Nullable<R>>,
options?: UseDocumentOptions
): _RefFirestore<_InferReferenceType<R>> // this one can't be null or should be specified in the converter
): _RefFirestore<_InferReferenceType<R> | undefined> // this one can't be null or should be specified in the converter

/**
* Creates a reactive collection (usually an array) of documents from a collection ref or a query from Firestore.
Expand All @@ -263,14 +263,12 @@ export function useDocument<
export function useDocument<T>(
documentRef: _MaybeRef<_Nullable<DocumentReference>>,
options?: UseDocumentOptions
): _RefFirestore<VueFirestoreDocumentData<T>>
): _RefFirestore<VueFirestoreDocumentData<T> | undefined>

export function useDocument<T>(
documentRef: _MaybeRef<_Nullable<DocumentReference<unknown>>>,
options?: UseDocumentOptions
):
| _RefFirestore<VueFirestoreDocumentData<T> | null>
| _RefFirestore<VueFirestoreDocumentData<T> | null> {
): _RefFirestore<VueFirestoreDocumentData<T> | undefined> {
// no unwrapRef to have a simpler type
return _useFirestoreRef(documentRef, options) as _RefFirestore<
VueFirestoreDocumentData<T>
Expand Down
9 changes: 7 additions & 2 deletions tests/database/list.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -364,8 +364,13 @@ describe('Database lists', () => {
tds(() => {
const db = database
const databaseRef = _databaseRef
expectType<Ref<unknown[]>>(useList(databaseRef(db, 'todos')))
expectType<Ref<number[]>>(useList<number>(databaseRef(db, 'todos')))
expectType<Ref<VueDatabaseQueryData>>(useList(databaseRef(db, 'todos')))
expectType<string | undefined>(
useList(databaseRef(db, 'todos')).value?.[0]?.id
)
expectType<Ref<VueDatabaseQueryData<number>>>(
useList<number>(databaseRef(db, 'todos'))
)

// TODO: tests for id field
})
Expand Down
11 changes: 8 additions & 3 deletions tests/database/objects.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { mount } from '@vue/test-utils'
import { describe, expect, it } from 'vitest'
import {
UseDatabaseRefOptions,
useList,
useObject,
VueDatabaseDocumentData,
_RefDatabase,
Expand Down Expand Up @@ -196,7 +195,13 @@ describe('Database objects', () => {
tds(() => {
const db = database
const databaseRef = _databaseRef
expectType<Ref<unknown[]>>(useList(databaseRef(db, 'todos')))
expectType<Ref<number[]>>(useList<number>(databaseRef(db, 'todos')))
expectType<Ref<unknown>>(useObject(databaseRef(db, 'todo')))
expectType<Ref<{ name: string } | null | undefined>>(
useObject<{ name: string }>(databaseRef(db, 'todo'))
)
expectType<undefined | string>(useObject(databaseRef(db, 'todo')).value?.id)
expectType<Ref<number | null | undefined>>(
useObject<number>(databaseRef(db, 'todo'))
)
})
})
31 changes: 21 additions & 10 deletions tests/firestore/document.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
} from 'firebase/firestore'
import { expectType, setupFirestoreRefs, tds, firestore } from '../utils'
import { nextTick, ref, shallowRef, unref, type Ref } from 'vue'
import { _MaybeRef } from '../../src/shared'
import { _MaybeRef, _Nullable } from '../../src/shared'
import {
useDocument,
VueFirestoreDocumentData,
Expand Down Expand Up @@ -243,14 +243,17 @@ describe(
finished: boolean
}

expectType<Ref<DocumentData | null>>(useDocument(itemRef))
expectType<Ref<DocumentData | null | undefined>>(useDocument(itemRef))
// @ts-expect-error
expectType<Ref<number | null>>(useDocument(itemRef))

// Adds the id
// FIXME: this one is any but the test passes
expectType<string>(useDocument(doc(db, 'todos', '1')).value.id)
expectType<string>(useDocument(doc(db, 'todos', '1')).value?.id)
expectType<string>(useDocument<TodoI>(doc(db, 'todos', '1')).value!.id)
expectType<_Nullable<TodoI>>(
useDocument<TodoI>(doc(db, 'todos', '1')).value
)
expectType<string>(useDocument<unknown>(doc(db, 'todos', '1')).value!.id)
useDocument(
doc(db, 'todos').withConverter<TodoI>({
Expand All @@ -261,28 +264,36 @@ describe(
toFirestore: (todo) => todo,
})
// @ts-expect-error: no id with custom converter
).value.id
).value?.id

expectType<Ref<number | null>>(useDocument<number>(itemRef))
expectType<Ref<number | null>>(useDocument<number>(itemRef).data)
expectType<Ref<number | null | undefined>>(useDocument<number>(itemRef))
expectType<Ref<number | null | undefined>>(
useDocument<number>(itemRef).data
)
// @ts-expect-error
expectType<Ref<string | null>>(useDocument<number>(itemRef))

const refWithConverter = itemRef.withConverter<number>({
toFirestore: (data) => ({ n: data }),
fromFirestore: (snap, options) => snap.data(options).n as number,
})
expectType<Ref<number>>(useDocument(refWithConverter))
expectType<Ref<number>>(useDocument(refWithConverter).data)
expectType<Ref<number | number | undefined>>(
useDocument(refWithConverter)
)
expectType<Ref<number | number | undefined>>(
useDocument(refWithConverter).data
)
// should not be null
useDocument(refWithConverter).value.toFixed(14)
useDocument(refWithConverter).value?.toFixed(14)
// @ts-expect-error: string is not assignable to number
expectType<Ref<string>>(useDocument(refWithConverter))
// @ts-expect-error: no id when a custom converter is used
useDocument(refWithConverter).value.id

// destructuring
expectType<Ref<DocumentData | null>>(useDocument(itemRef).data)
expectType<Ref<DocumentData | null | undefined>>(
useDocument(itemRef).data
)
expectType<Ref<FirestoreError | undefined>>(useDocument(itemRef).error)
expectType<Ref<boolean>>(useDocument(itemRef).pending)
})
Expand Down

0 comments on commit 76e1527

Please sign in to comment.