Как исправить ошибку Typescript "Возможно, объект не определен" - PullRequest
1 голос
/ 30 марта 2019

Я создаю облачную функцию, которая будет использовать Stripe API для обработки платежей. Это в рамках проекта Firebase. Когда я запускаю firebase deploy, я получаю сообщение об ошибке "Возможен объект" undefined "" const existingSource = customer.sources.data.filter( (s) => s.id === source).pop(); Я не уверен, как решить эту проблему.

Вот мой index.ts

import * as functions from 'firebase-functions'; 

export { stripeAttachSource } from './sources';
export { stripeCreateCharge, stripeGetCharges } from './charges';
export const testFunction = functions.https.onCall( async (data, context) => {
    const uid = context.auth && context.auth.uid; 
    const message = data.message; 
    return `${uid} sent a message of ${message}`
}); 

вот мои источники.тс

import * as functions from 'firebase-functions';
import { assert, assertUID, catchErrors } from './helpers';
import { stripe } from './config'; 
import { getOrCreateCustomer } from './customers';

/** Attachs a payment source to a stripe customer account.  */
export const attachSource = async(uid: string, source: string) => {

    const customer = await getOrCreateCustomer(uid); 

    const existingSource = customer.sources.data.filter( (s) => s.id === source).pop(); 
    if (existingSource != undefined) {
        let t = existingSource; 
        return t; 
    } else {
        await stripe.customers.createSource(customer.id, { source: source }); 
        //update default
        return await stripe.customers.update(customer.id, { default_source: source}); 
    }
}

///////// DEPLOYABLE FUNCTIONS //////////////////////////////////
export const stripeAttachSource = functions.https.onCall( async ( data, context) => {
    const uid = assertUID(context); 
    const source = assert(data, 'source'); 

    return catchErrors(attachSource(uid, source));  
})

Здесь customer.ts, где существует getorCreateCustomer

import { assert } from './helpers'; 
import {db, stripe } from './config'; 


/** 
Read the user document from Firestore
 */
export const getUser = async(uid: string) => {
    return await db.collection('users').doc(uid).get().then(doc => doc.data()); 

}

/**
 * Gets a customer from Stripe
 */
export const getCustomer = async(uid: string) => {
    const user = await getUser(uid); 
    return assert(user, 'stripeCustomerId'); 
}

/**
Updates the user document non-desctructively
 */
export const updateUser = async(uid: string, data: Object) => {
    return await db.collection('s-users').doc(uid).set(data, { merge: true }); 
}

/**
Takes a Firebase user and creates a Stripe customer account
 */
export const createCustomer = async(uid: any) => {
    const customer = await stripe.customers.create({
        metadata: { firebaseUID: uid }
    })
    await updateUser(uid, {stripeCustomerId: customer.id })

    return customer; 
}

/** Read the stripe customer ID from firestore, or create a new one if missing */
export const getOrCreateCustomer = async(uid: string) => {
    const user = await getUser(uid); 
    const customerId = user && user.stripeCustomerId; 

    //if missing customerId, create it
    if (!customerId) {
        return createCustomer(uid); 
    }
    else {
        return stripe.customers.retrieve(customerId); 
    }
}

enter image description here

Ответы [ 2 ]

3 голосов
/ 30 марта 2019

На основании определений и содержимого ваших функций TypeScript не может определить тип возвращаемого значения getOrCreateCustomer. Предполагается, что он может вернуть неопределенное значение, и его строгий режим вызывает у вас тот факт, что вы можете ссылаться на свойство неопределенного объекта, что может привести к ошибке во время выполнения.

Что вам нужно сделать, это объявить возвращаемый тип как нечто, что невозможно определить, и убедиться, что код в теле функции верен в этой гарантии (в противном случае вы получите новую ошибку) .

Если вы не можете этого сделать (но вы действительно должны это делать), вы можете вместо этого отключить строгий режим в своем файле tsconfig.json, поскольку именно это обеспечивает такой уровень корректности в вашем коде.

Я предлагаю первый вариант, даже если вам нужно написать больше строк кода, так как он лучше использует систему ввода TypeScript.

1 голос
/ 30 марта 2019

То, что упоминал @Doug, но вы также можете написать свою логику, чтобы убедиться, что каждая часть customer.sources.data не является неопределенной ...

, то есть:

const { sources } = customer

if (sources) {
  const { data } = sources 
  if (data) {
     // then filter / etc etc ...
  }
}
...