created: 2023-08-25T01:55:31.610Z

zodで数値を表現した文字列を扱う

zodを使っていて、UIフォームから取り出した値は数値っぽい文字列型なことがある。

typeof "12345"  // => string

そういった値を z.number() でチェックにかけてしまうとバリデーションエラーになってしまう。

エラーの様子

> const { z } = require("zod");
undefined
> z.number().parse("123")
Uncaught:
[
  {
    "code": "invalid_type",
    "expected": "number",
    "received": "string",
    "path": [],
    "message": "Expected number, received string"
  }
]

...

  issues: [
    {
      code: 'invalid_type',
      expected: 'number',
      received: 'string',
      path: [],
      message: 'Expected number, received string'
    }
  ],
  addIssue: [Function (anonymous)],
  addIssues: [Function (anonymous)],
  name: 'ZodError',
  errors: [
    {
      code: 'invalid_type',
      expected: 'number',
      received: 'string',
      path: [],
      message: 'Expected number, received string'
    }
  ]
}

どうすればいいか

もちろんライブラリで対応できてドキュメントの basic usage の次に書いてある。 coerce を使えばよい。

> z.coerce.number().parse("123")
123

もうすこし

coerce は簡単な型変換をするための属性で、たとえば 0|1|null などを真偽値型に変換するなどにも使える。

> z.coerce.boolean().parse("123")
true
> z.coerce.boolean().parse(null)
false

いろいろできる。文字列を Date 型にもできる。

> z.coerce.date().parse("2000-01-01 12:34:56")
2000-01-01T03:34:56.000Z
> z.coerce.date().parse("2000-01-01 12:34:56Z")
2000-01-01T12:34:56.000Z

参考

過去にはよい方法がなかったようで、古い記事だと coerce が出てこないかもしれない。

ザ・ロングラン 人生を走り出す日まで (Kindle Single)
[ad] ザ・ロングラン 人生を走り出す日まで (Kindle Single)
ミシュカ シュバリー, 村山 美雪 (Kindle版)