TypeScriptは、非構造化オブジェクトのタイプを認識しません

2
2022.01.14

私はこのようにコレクションを取得するために基本的なFirebase呼び出しを行っています

import { getFirestore, collection, getDocs } from "firebase/firestore";

import { Invoice } from "../models/Invoice";

const db = getFirestore();

export const getInvoicesCollection = async () => {
  try {
    const snapshot = await getDocs(collection(db, "invoices"));

    const docs: Invoice[] = snapshot.docs.map((doc) => ({
      ...doc.data(),
    }));

    console.log(docs);
  } catch (error) {
    console.error(error);
  }
};

export default getInvoicesCollection;

Firebase によって返される応答オブジェクトはかなり太っているので、必要なものはすべてこのパートの新しいものにマッピングします。

const docs: Invoice[] = snapshot.docs.map((doc) => ({
  ...doc.data(),
}));

console.log(docs);

そして、私はブラウザで結果を得る:

enter image description here

しかし、TypeScriptは次のように不平を言います。

Type '{ [x: string]: any; }[]' is not assignable to type 'Invoice[]'.
Type '{ [x: string]: any; }' is missing the following properties from type 'Invoice': id, createdAt, paymentDue, description, and 8 more.

私がそれを正しく取得した場合、私の変数は、文字列であり、何でもできる単一のプロパティを持つオブジェクトの配列であると言いますか?オブジェクトが実際にどのように見えるかを知る方法はありますか?

回答
2
2022.01.14

doc.data()が返す型は{ [x: string]: any; }で、キーに文字列を持つ任意の数またはプロパティを持つオブジェクトを意味し、各オブジェクトは任意の値を持つことができます。データベースはほとんど何でも返すことができるので、これよりも具体的な型を見つけ出す方法はありません。

したがって、typescriptは型を把握できないので、型が何であるかをアサートする必要があります。

const docs: Invoice[] = snapshot.docs.map((doc) => ({
  ...doc.data() as Invoice,
}));

注意: 型アサーションを使用することで、作業をチェックしないように typescript に指示し、ただ信頼しています。間違いを犯し、データベースに実際に異なる種類のオブジェクトが含まれている場合、typescript はそのことをユーザーに伝えることはできません。