Upgrade to Pro — share decks privately, control downloads, hide ads and more …

GraphQL_nullability__state_of_the_union.pdf

mbonnin
December 14, 2023
10

Β GraphQL_nullability__state_of_the_union.pdf

mbonnin

December 14, 2023
Tweet

Transcript

  1. { "data" { "video": { "id": "42", "title": "GraphQL 101",

    "uploadDate": "2023-12-03T22:26:46Z" } } }
  2. Error null != Semantic null { "errors": [ { "message":

    "cannot resolve title", "path": "video.title" } ] "data": { "video": { "id": "42", "title": null } } }
  3. Terminology β€’ Error null β—¦ Exceptional case β—¦ Has an

    error in the errors array β€’ Semantic null β—¦ Business case β—¦ No error in the errors array
  4. Post mortem β€’ New feature: video upload β€’ During the

    upload, a video doesn’t have a title yet β€’ This was a backward compatible schema change!
  5. @Composable fun VideoItem(response: Response) { if (response.errors.isNotEmpty()) { Error() }

    else { if (response.data.video.title == null) { Text(text = "This video doesn't have a title yet") } else { Text(text = response.data.video.title) } } }
  6. @Composable fun VideoItem(response: Response) { if (response.errors.any { it.path ==

    "video.title" }) { Error() // Can't display a video without a title } else { if (response.data.video.title != null) { Text(text = "This video does not have a title yet") } else { Text(text = response.data.video.title!!) } if (response.errors.any { it.path == "video.viewCount" }) { // Skip viewCount } else { Text(text = "${response.data.video.viewCount!!} + views") } } } Partial data
  7. GraphQL is missing types Your favorite type-safe language GraphQL string

    β†’ String! string | null β†’ String string | error β†’ String string | null | error β†’ String
  8. Documentation type Video { """ The title of the Video

    null if the video has just been uploaded """ title: String """ Number of times this video has been watched Never null unless there is an error """ viewCount: Int }
  9. Nullability working group 2021 Client Controlled Nullability May 2023 sub

    working group Sep 2023 GraphQL conf True nullability Asterisk Interrobang Oct 2023 semantic-non-null @strictNullability @catch graphql/nullability-wg
  10. Nullability working group 2021 Client Controlled Nullability May 2023 sub

    working group Sep 2023 GraphQL conf True nullability Asterisk Interrobang Oct 2023 semantic-non-null @strictNullability @catch graphql/nullability-wg
  11. Asterisk string β†’ String! string | null β†’ don’t use

    string | error β†’ String* string | null | error β†’ String graphql/graphql-spec/pull/1048 Never a semantic null
  12. Strict nullability string β†’ String! string | null β†’ don’t

    use string | error β†’ String string | null | error β†’ String? graphql/graphql-wg/discussions/1410 schema @strictNullability { query: Query } Never a semantic null
  13. Conclusion β€’ null is not always what it seems! β€’

    be aware of the tradeoffs β€’ document nullability β€’ get involved!
  14. Input nullability string β†’ String! string | null β†’ String

    string | absent β†’ String string | null | absent β†’ String graphql/graphql-spec/issues/476
  15. Semantic non-null string β†’ String! string | null β†’ don’t

    use string | error β†’ !String string | null | error β†’ String graphql/graphql-spec/pull/1065
  16. Interrobang string β†’ String! string | null β†’ don’t use

    string | error β†’ String!? string | null | error β†’ String graphql/graphql-spec/pull/1046
  17. string β†’ String! string | null β†’ don’t use string

    | error β†’ String @semanticNonNull string | null | error β†’ String @semanticNonNull
  18. Problem 2: what default? β€’ Fail the whole query β—¦

    Easy β—¦ Fragile β€’ Handle field errors β—¦ Hard β—¦ Robust
  19. Opting in error handling β€’ Start easy β€’ Add error

    handling progressively fragment VideoDetails on Video { video { title # opt-in error handling viewCount @catch } } facebook/relay/issues/4416
  20. Opting in error handling fragment VideoDetails on Video { video

    { title # opt-in error handling viewCount @catch } } sealed interface Result<T> { class Success(val value: T): Result class Failure(val error: error): Result } Video( val title: String val viewCount: Result<Int> ) apollographql/apollo-kotlin/pull/5405
  21. Client Controlled Nullability graphql/graphql-wg/blob/main/rfcs/ClientControlledNullability.md fragment videoDetails on Video { video

    { # We need title to display a video title! # It's okay to fail viewCount viewCount? } }
  22. string β†’ String string | null β†’ String? string |

    error β†’ String @throws string | null | error β†’ String? @throws Exceptions graphql/nullability-wg/discussions/39
  23. Exceptions string β†’ don’t use string | null β†’ don’t

    use string | error β†’ String string | null | error β†’ String? graphql/nullability-wg/discussions/39