3

Currently cleaning up a bit of code and rewritting a lot in typescript. What I found what made me curious is the following code:

    const userRef = firestore.collection('users').doc(userId);
    const userDoc = await userRef.get();

    if (userDoc.exists) {
        const userData = userDoc.data();

        const currentUserBalance = userData.balance ? userData.balance : 0;
    }

Now Typescript will complain that userData is possibily undefined, but the Documents .data() cannot be undefined when I check for the document existing above in my if block. Just curious on why that happens and if I have a logic issue here or not.

1
  • If the provided answer was helpful for you, please mark it as correct. Commented Aug 31, 2019 at 20:44

2 Answers 2

6

TypeScript doesn't have any knowledge of the relationship between exists and data(). It just knows the signature of data() says that the return value can be DocumentSnapshot or undefined. So, you must satisfy the compiler by either:

  1. First checking for "truthiness", then use the results if so:
const data = userDoc.data()
if (data) {
    // In this block, data is now typed as just DocumentData,
    // undefined is no longer an option.
}
  1. Telling TypeScript that you know for sure that the results will be "truthy" by using the ! operator:
const data = userDoc.data()!  // data is now typed as just DocumentData
Sign up to request clarification or add additional context in comments.

2 Comments

@Doug Stevenson you actually only need one exclamation mark as documented here
@lukasgeiter That's what I get for using Kotlin as well.
2

Unfortunately, even though Firestore adapters both for Node.js and the web are written mainly in TypeScript, they aren't designed for the language.

To solve the problem, I wrote Typesaurus, TypeScript-first ORM (or ODM if you wish) that solves this problem:

import { get, collection } from './src'
type User = { name: string }
const users = collection<User>('users')

async function main() {
  const user = await get(users, 'qwe') // get will return document or undefined
  if (user) {
    console.log(user.data.name) // user is Doc<User>
  } else {
    // user is undefined
  }
}

main()

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.