Typing issue on addAction's defaultValue

Plop, it’s me again. It seems I’m hitting every possible typing weirdness, so here we go again!

Feature(s) impacted

Smart actions when using handlers with nullable return values instead of flat values for defaultValue et al.

Expected behavior

I expected to be able to have a handler return either string or null depending on the circumstance, which is not the case.

I’m putting this above the below section because it gets long.

Observed behavior

The following code compiles fine:

export default function UserCustomizer(
  users: CollectionCustomizer<Schema, 'User'>,
) {
  users.addAction('ban', {
    scope: 'Single',
    form: [
      {
        type: 'String',
        label: 'Reason',
        isRequired: true,
        defaultValue: () => {
          return 'Profanity'
        },
      },
    ],
    execute() {
      // todo
    },
  })
}

But if we want to have a more dynamic defaultValue, let’s say only for some teams:

export default function UserCustomizer(
  users: CollectionCustomizer<Schema, 'User'>,
) {
  users.addAction('ban', {
    scope: 'Single',
    form: [
      {
        type: 'String',
        label: 'Reason',
        isRequired: true,
        defaultValue: (context) => {
          if (context.caller.team === 'PROFANITY_CHECKERS') {
            return 'Profanity'
          }
          return null
        },
      },
    ],
    execute() {
      // todo
    },
  })
}

(I’m just using the teams here as a dummy example)

We then get a compilation TS2322 error which is pretty large so I’ll just paste it:

This is only an issue at compile-time. The front-end works fine if we @ts-expect-error on this line.

Interestingly, this borks up all handlers, even on other fields. That is, this code is fine:

export default function UserCustomizer(
  users: CollectionCustomizer<Schema, 'User'>,
) {
  users.addAction('ban', {
    scope: 'Single',
    form: [
      {
        type: 'String',
        label: 'Reason',
        isRequired: true,
      },
      {
        type: 'Date',
        label: 'BannedUntil',
        isRequired: (context) => context.caller.team !== 'BOFH',
        defaultValue: 'PROFANITY',
      },
    ],
    execute() {
      // TODO
    },
  })
}

But this code has errors both on the Reason field and the BannedUntil field:

export default function UserCustomizer(
  users: CollectionCustomizer<Schema, 'User'>,
) {
  users.addAction('ban', {
    scope: 'Single',
    form: [
      {
        type: 'String',
        label: 'Reason',
        isRequired: true,
        defaultValue: (context) => {
          if (context.caller.team === 'PROFANITY_CHECKERS') {
            return 'Profanity'
          }
          return null
        },
      },
      {
        type: 'Date',
        label: 'BannedUntil',
        isRequired: (context) => context.caller.team !== 'BOFH',
        defaultValue: 'PROFANITY',
      },
    ],
    execute() {
      // TODO
    },
  })
}

So I’m thinking either I’m really not allowed to have a nullable defaultValue, or I’m doing something wrong elsewhere. Last and least likely hypothesis, the typings are berken.

Halp :smiley:

Context

  • Agent technology: nodejs
  • Agent (forest package) name & version: 1.40.1 with sequelize 6.37.3 and sequelize-typescript 2.1.6
  • Database type: MSSQL
  • Recent changes made on your end if any: Migrating from old agent.

Hello @kll ,
Thanks for the feedback. Indeed, the typings seems broken is this case when strictNullChecks are enabled. I created a bug ticket on our side.
If the other handlers are ok when you ts-ignore the source error, it seems to be the best temporary solution.
If this is an option for you, you can also disable the strictNullChecks in your ts config.
If none of these is possible, I’m afraid you’ll have to use a workaround like “null as unknown as number” until the bug is fixed.

Kind regards,
Enki

2 Likes

Hi @Enki,

Thank you for your reply!
I’m now using a pretty similar solution:

export default function UserCustomizer(
  users: CollectionCustomizer<Schema, 'User'>,
) {
  users.addAction('ban', {
    scope: 'Single',
    form: [
      {
        type: 'String',
        label: 'Reason',
        isRequired: true,
        // Explicitly type the return value
        defaultValue: (context): string => {
          if (context.caller.team === 'PROFANITY_CHECKERS') {
            return 'Profanity'
          }
          // @ts-expect-error typing issue
          return null
        },
      },
    ],
    execute() {
      // TODO
    },
  })
}
1 Like