Iterable / react-native-sdk

MIT License
36 stars 32 forks source link

IterableInAppMessage.createdAt type seems inconsistent with what's specified in the TS declaration - causing crashes #581

Open alex-a-pereira opened 2 days ago

alex-a-pereira commented 2 days ago

Issue

The type is declared to be a Date (potentially undefined)

// https://github.com/Iterable/react-native-sdk/blob/master/ts/IterableInAppMessage.ts
declare class IterableInAppMessage {
    /**
     * the ID for the in-app message
     */
    readonly messageId: string;
    /**
     * the campaign ID for this message
     */
    readonly campaignId: number;
    /**
     * when to trigger this in-app
     */
    readonly trigger: IterableInAppTrigger;
    /**
     * when was this message created
     */
    readonly createdAt?: Date;
    /**

However when i add the following logging:

    console.log('=====================================')
    console.log(latestInboxMessage?.itbInAppMessage?.createdAt)
    console.log(typeof latestInboxMessage.itbInAppMessage.createdAt)

I see that typeof createdAt is a string when logging from Android and a Number when logging from iOS

Android logs: i included the error that is thrown that's causing my app to crash (android only)

LOG  1720797936904
 LOG  string
 ERROR  Error: fromMillis requires a numerical input, but received a string with value 1720797936904

iOS Logs

LOG 1720797936904
 LOG  number

Investigation (so far)

I'm not sure what is causing the typeof to be different between iOS/Android, however by reading the code it doesn't look like the typing of Date | undefined is correct. dateObject.setUTCMilliseconds returns a Number, not a Date

// https://github.com/Iterable/react-native-sdk/blob/master/ts/IterableInAppMessage.ts#L115
    let createdAt = dict["createdAt"]
    if (createdAt) {
      var dateObject = new Date(0)
      createdAt = dateObject.setUTCMilliseconds(createdAt)
    }
alex-a-pereira commented 2 days ago

If anyone else runs into this issue this is how I fixed in my codebase temporarily:

Using patch-package make this patch so TS will fail to compile if I don't account for the typings

diff --git a/node_modules/@iterable/react-native-sdk/js/IterableInAppMessage.d.ts b/node_modules/@iterable/react-native-sdk/js/IterableInAppMessage.d.ts
index b363e19..41efec4 100644
--- a/node_modules/@iterable/react-native-sdk/js/IterableInAppMessage.d.ts
+++ b/node_modules/@iterable/react-native-sdk/js/IterableInAppMessage.d.ts
@@ -19,7 +19,7 @@ declare class IterableInAppMessage {
     /**
      * when was this message created
      */
-    readonly createdAt?: Date;
+    readonly createdAt?: string | number | Date;
     /**
      * when to expire this in-app (undefined means do not expire)
      */

Then I made a helper function in my code

const parseDateFromUnknownFormat = (iterableDate: string | number | Date | undefined): Date | null => {
  if (iterableDate == null) { return null }

  if (typeof iterableDate === 'string') {
    return new Date(parseInt(iterableDate))
  }

  if (typeof iterableDate === 'number') {
    return new Date(iterableDate)
  }

  return iterableDate
}
Ayyanchira commented 2 days ago

Thanks for reporting this issue @alex-a-pereira ! and appreciate the workaround suggested for fellow developers. Will have this issue flagged internally for the team to fix.