question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

optional().default() getter doesn't allow returning undefined

See original GitHub issue

Given the following snippet:

import { z } from "zod";

const checkIfOnPath = (executableName: string) => false;

const parsed = z.string()
  .nonempty()
  .optional()
  .default(() => ["a", "b", "c"].find(checkIfOnPath))
  .parse(undefined);

I get this error:

No overload matches this call.
  Overload 1 of 2, '(def: string): ZodDefault<ZodOptional<ZodString>>', gave the following error.
    Argument of type '() => string | undefined' is not assignable to parameter of type 'string'.
  Overload 2 of 2, '(def: () => string): ZodDefault<ZodOptional<ZodString>>', gave the following error.
    Type 'string | undefined' is not assignable to type 'string'.
      Type 'undefined' is not assignable to type 'string'.(2769)

(TS Playground link.)

My expectation is that .default() with a function on ZodOptional<ZodString> should be able to return string | undefined, but it only accepts a function that returns string.

Further, at runtime this works just fine – if the default getter returns undefined, .parse() doesn’t throw, and its return value is undefined as I expect.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Reactions:2
  • Comments:6 (1 by maintainers)

github_iconTop GitHub Comments

1reaction
scotttrinhcommented, Feb 1, 2022

@lostfictions

But just to make sure I understand, this means that .optional().default() and .default() are effectively the same thing? Given this constraint, the former is effectively redundant and there’s never a reason one would reach for it, right?

Correct!

1reaction
scotttrinhcommented, Feb 1, 2022

The spirit and intention of default is to return a value of the base type (in this case string), as you’ve noticed. Since you’d like to define an optional default here, you can use transform instead:

CodeSandbox

const schema = z
  .string()
  .nonempty()
  .optional()
  .transform(
    (maybeString) => maybeString ?? ["a", "b", "c"].find(checkIfOnPath)
  );
Read more comments on GitHub >

github_iconTop Results From Across the Web

Should Java 8 getters return optional type? - Stack Overflow
By default, it assumes nothing is allowed to be null unless it's annotated so. This way, you don't have to worry about null...
Read more >
undefined instead of default for optional fields ? #1572 - GitHub
create() returns an object, that do not have the optional int32 foo = 1 field explicitly defined, but accessing such object's msg.foo will ......
Read more >
Optional chaining (?.) - JavaScript - MDN Web Docs - Mozilla
When used with function calls, it returns undefined if the given function does not exist. This results in shorter and simpler expressions when ......
Read more >
Tired of Null Pointer Exceptions? Consider Using Java SE 8's ...
The variable computer is of type Optional<Computer> , so it is perfectly correct to call the map method. However, getSoundcard() returns an object...
Read more >
@Getter and @Setter - Project Lombok
Never write public int getFoo() {return foo;} again. ... A default getter simply returns the field, and is named getFoo if the field...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found