A little Typescript help

I got Pack Studio access! :tada:

To start, I’ve been hacking away on a little pack of date handling tools, and wanted to try a date range column format. I’m running into a Typescript bug, which has me a bit stumped as I’m not too familiar with TS. Here’s the column code (make sure to scroll):

const DateRangeSchema = coda.makeObjectSchema({
  type: coda.ValueType.Object,
  properties: {
    startDate: {
      description: "The beginning of the event or date range",
      type: coda.ValueType.Number,
      codaType: coda.ValueHintType.Date,
      required: true,
    },
    endDate: {
      description: "The end of the event or date range",
      type: coda.ValueType.Number,
      codaType: coda.ValueHintType.Date,
      required: true,
    },
  }
})

pack.addColumnFormat({
  name: "DateRange",
  instructions: "An event spanning from a start date to an end date. Feed it a list of the start date and end date - e.g. ListCombine(StartDate, EndDate)",
  formulaName: "DateRange",
  formulaNamespace: "Deprecated", // Will be removed shortly
});

pack.addFormula({
  name: "DateRange",
  description: "Return a DateRange object from a list of the start date and end date",
  parameters: [
    coda.makeParameter({
      name: "dates",
      type: coda.ParameterType.DateArray,
      description: "A list/array of the start and end dates",
    }),
  ],
  resultType: coda.ValueType.Object,
  schema: DateRangeSchema,

  execute: async function ([dates], context) {
    return {
      startDate: dates[0],
      endDate: dates[1],
    };
  },
});

I get a red underline on execute, and build fails with the following error referencing that line#:

Type '([dates]: ParamValues<[ParamDef<ArrayType<Type.date>>]>, context: ExecutionContext) => Promise<{ startDate: Date; endDate: Date; }>' is not assignable to type '(((params: ParamValues<[ParamDef<ArrayType<Type.date>>]>, context: ExecutionContext) => boolean | Promise<boolean>) & ((params: ParamValues<...>, context: ExecutionContext) => boolean | Promise<...>)) | (((params: ParamValues<...>, context: ExecutionContext) => number | Promise<...>) & ((params: ParamValues<...>, co...'. Type '([dates]: ParamValues<[ParamDef<ArrayType<Type.date>>]>, context: ExecutionContext) => Promise<{ startDate: Date; endDate: Date; }>' is not assignable to type '((params: ParamValues<[ParamDef<ArrayType<Type.date>>]>, context: ExecutionContext) => boolean | Promise<boolean>) & ((params: ParamValues<...>, context: ExecutionContext) => boolean | Promise<...>)'. Type '([dates]: ParamValues<[ParamDef<ArrayType<Type.date>>]>, context: ExecutionContext) => Promise<{ startDate: Date; endDate: Date; }>' is not assignable to type '(params: ParamValues<[ParamDef<ArrayType<Type.date>>]>, context: ExecutionContext) => boolean | Promise<boolean>'. Type 'Promise<{ startDate: Date; endDate: Date; }>' is not assignable to type 'boolean | Promise<boolean>'. Type 'Promise<{ startDate: Date; endDate: Date; }>' is not assignable to type 'Promise<boolean>'. Type '{ startDate: Date; endDate: Date; }' is not assignable to type 'boolean'.

If I hard code some integer values into the startDate and endDate properties of that last returned object, it works fine. What am I doing wrong here?

Hmmm. Doesn’t seem like anything is hinting at the function to return a boolean value.

Does turning it off and on again help? :smiley: (I’m serious, sometimes leaving the pack studio and reopening it again would fix some strange TS errors)

P.S. I can reproduce it as well. Could be a bug :man_shrugging:

Thanks for looking into this @Paul_Danyliuk

I have a feeling I’m just missing quotation marks somewhere or something but yeah, not sure what it means about looking for a Boolean value (I expect something deeper under the hood in the bowels of the pack library?). Maybe a bug indeed.

I’ll play around with it a bit more, maybe mixing up my parameter types to see if that makes any difference.

No the solution but regarding “turn off and on”:

When I comment out codaType: coda.ValueHintType.Date, and then comment it back in ath the endDate Param, I can build without an error :smiley:
After a couple of seconds after building, the error shows up again – but the pack is built and formula works in the doc.

1 Like

Haha ok, sounds like a bug :joy:

I have seen this as well.

You know what fixed it? This:

image

I’m also very curious where this comes from:

Whaaa… Just to be clear though, while that fixes it now, it’s not really the “correct” thing to do, right? Like it will cause me problems later on if I can’t rely on those props being coercible to integers which is how Coda stores dates under the hood? (actually this makes me realize I’m not sure on the underlying storage type - I have in my head they do the Unix epoch thing?)

And yes, very weird about the end date 11:59:59…

Gotta love trying to model time with computers. For some reason there’s just nothing harder.

(That’s why we need a pack! :wink:)

Correct.

I think the issue is here -

type: coda.ParameterType.DateArray,

I believe it might work with:

type: coda.ParameterType.NumberArray,

Interesting. So in api_types.ts around line 600 where they’re talking about some of their human-friendly ranges like “next 7 days”:

/*
 * Date array parameters are meant to represent date ranges. A date range can
 * be a fixed range, e.g. April 1, 2020 - May 15, 2020, or it can be a "live"
 * range, like "last 30 days".
 *
 * At execution time, a date range will always be passed to a pack as an
 * array of two specific dates, but for many use cases, it is necessary
 * to provide a default value that is a "live" range rather than hardcoded
 * one.
*/
...

I’m going to dig into this a bit more to make sure I understand the other contexts date ranges get used in.

But also, I think my issue may be that Coda is using JS Date objects rather than just a vanilla integer to store the date values?

I don’t know if it is or isn’t. In type declarations, it seems that coda.ValueTypeHint.Date (and T/DT) are coercible from both a Number and a String.

I also always thought that Coda dates were numbers, but recently it seems like it’s a data type on its own (an object with a few fields) that is just auto-casted to a Number for the formula language. Even in a number form it’s not a Unix epoch but “Excel time”, a 1900/1/1-based number where the decimal part encodes time and the integer part the number of days since 1900/1/1.

EDIT: Oh, and yeah, the DateArray data type could be responsible for converting the end date to behave like inclusive (i.e. add the 23:59:59)

(tangent, is everyone using the Pack Studio web UI? I was all ready to get my dev environment set up locally but the web experience is basicaly VSCode anyway - working pretty well :man_shrugging: )

1 Like

It’s unnecessary for learning, rapid experimentation, etc. And the web editor is pretty good - not the best, but it is functional and pretty reliable. So, I use it mostly. The CLI will be needed if we need to introduce some additional libraries (I think).

Same here, was setting up locally and tested on a pack, but then switched back to web. It just works, and is easy and fast. Only thing I miss is multi-files. If you have 2-3 formulas with bigger schemas or even complex parts like dynamic sync tables, its annoying to have all in one file in the web ui.

So the problem here is that there are two ways to return a Date to Coda: as a Number or as a String. At the moment you can’t actually return a Date object, which I understand is confusing. When using a string Coda will try to parse the string value as a date, and when using a number it should be the number of seconds since the epoch. (I’m actually working on adding more documentation about data types this week, so you ran into this problem a few days too soon :slight_smile: )

Unfortunately when there is a mismatch between the type and codaType the error message is extremely unhelpful, talking about booleans for some reason. I’ve already filed a bug about that issue internally and hopefully we can improve it.

7 Likes

Thanks @Eric_Koleda !

In this situation, what would you recommend using for types? start_date and end_date get type: coda.ValueType.String and codaType: coda.ValueHintType.Date? And then pack them into a dateArray for my parameter?

How best to handle the potential for incorrect (i.e. non-Date-parsable) input?

Or should I just wait for your documentation updates? :slight_smile:

@Nick_HE - This docs I mentioned are now live:

https://coda.github.io/packs-sdk/guides/basics/data-types/#dates-and-times

In general you’re fine using either strings or numbers for dates, both work well. On the parameter side dates are returned as JavaScript Date objects. If the user passes in an invalid date it will fail with an error before your code is even run, so you’re safe to assume it’s a valid date by the time it hits your code.

3 Likes

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.