Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Find APIs should possibly return undefined #76

Closed
camchenry opened this issue Apr 19, 2021 · 5 comments
Closed

Find APIs should possibly return undefined #76

camchenry opened this issue Apr 19, 2021 · 5 comments

Comments

@camchenry
Copy link
Contributor

camchenry commented Apr 19, 2021

Hi, I am having multiple issues, the biggest of which currently is that the findMany and findFirst APIs do not allow for the possibility of returning undefined, even though they may do so. This causes TypeScript to not be able to type check this properly and results in run-time type errors.

CodeSandbox example:
https://codesandbox.io/s/mswjs-undefined-type-error-omifi?file=/src/App.tsx

import { factory, primaryKey } from "@mswjs/data";
import {
  EntityInstance,
  PrimaryKeyDeclaration
} from "@mswjs/data/lib/glossary";
import * as faker from "faker";

const db = factory({
  user: {
    Id: primaryKey(faker.datatype.uuid),
    firstName: () => "random data here"
  }
});

// Seed the database
db.user.create({
  Id: "ab4f631c-cca4-498f-a5aa-4828352a7c69",
  firstName: "Test"
});

// Some time later, query the database:
// Get a user (e.g., GET /user/:userId call)
const user = db.user.findFirst({
  where: {
    Id: {
      equals: "ab4f631c-cca4-498f-a5aa-4828352a7dawdawdc69"
    }
  }
});

// OK
console.log("This will NOT cause a run-time type error: ", user?.firstName);

// ERROR
console.log("This will cause a run-time type error: ", user.firstName);

I think these APIs should have the type like T | undefined (where T is the entity) rather than just returning T unconditionally.

@kettanaito
Copy link
Member

Hey, @camchenry. Thank you for yet another suggestion!

Would T | null work for your use case? It'd be great to align the returned value, and we do use null for update/delete operations already:

data/src/glossary.ts

Lines 136 to 140 in f8da857

update(
query: QuerySelector<Value<Dictionary[ModelName], Dictionary>> & {
data: Partial<UpdateManyValue<Dictionary[ModelName], Dictionary>>
},
): EntityInstance<Dictionary, ModelName> | null

@marcosvega91
Copy link
Member

I have noticed this some day ago and put it in the pr #67. Today i'll rebase the branch

@camchenry
Copy link
Contributor Author

Yeah, T | null would work for me, and I'd imagine others as well. For pretty much all intents and purposes, I'd treat null and undefined interchangeably. For me, the main thing is being able to use the ??, and ?. operators to handle nullish values seamlessly, as well as doing a check like:

const entity = db.entity.findFirst(...);
if (!entity) {
  throw new Error(); // or return 404
}
// entity is now guaranteed to not be null/undefined

Thinking about it a little more though, this should probably only apply to the findFirst function, because it returns the entity directly rather than an array of entities. Because findFirst is analogous to Array.find and findMany is analogous to Array.filter?

@kettanaito
Copy link
Member

Agree on that: let's retain findMany returning an empty array in the case when no entities matched the query. I find it a more pleasant data type to work with (both results.length and results.map are intuitive on empty results).

@kettanaito
Copy link
Member

I believe with @67 merged findFirst and findMany now return the expected types:

data/src/glossary.ts

Lines 129 to 141 in 5cc1d73

/**
* Find a first entity matching the query.
*/
findFirst(
query: QuerySelector<Value<Dictionary[ModelName], Dictionary>>,
): Entity<Dictionary, ModelName> | null
/**
* Find multiple entities.
*/
findMany(
query: WeakQuerySelector<Value<Dictionary[ModelName], Dictionary>> &
BulkQueryOptions,
): Entity<Dictionary, ModelName>[]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants