Repository: colinhacks/zod
Pull request #4271 (2025-04-24 00:01:35)

Support recursive types in `z.object()`, drop `z..interface()`
> ⚠️ This PR contains breaking changes. `z.interface()` has been removed in its entirety.

! I finally figured out a way to support cyclical type inference in `z.object()`. I've been trying to get this working for years and thought it was impossible. 

![Screenshot 2025-04-29 at 15 08 52](https://github.com/user-attachments/assets/c632fd16-03b7-4fc8-be87-bbc2a25ff49c)

This new capability negates the primarily raison d'être of `z.interface()`. Thus this PR also:

- Removes `z.interface()`. 
- Removes `core.ZodObjectLike` (an interface that served as a shared parent for ZodObject and ZodInterface)
- Removes `optional: string[]` from `ZodObjectDef`. Optionality information is stored on the elements inside `shape`.


This is a major breaking change but Zod 4 is still in beta for two more weeks. I'm loathe to do a change of this magnitude but in general consolidating on a single object API is a huge win, so it's worth it.

coderabbitai[bot]: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- This is an auto-generated comment: skip review by coderabbit.ai -->

> [!IMPORTANT]
> ## Review skipped
> 
> Auto reviews are disabled on base/target branches other than the default branch.
> 
> 
> 
> Please check the settings in the CodeRabbit UI or the `.coderabbit.yaml` file in this repository. To trigger a single review, invoke the `@coderabbitai review` command.
> 
> You can disable this status message by setting the `reviews.review_status` to `false` in the CodeRabbit configuration file.

<!-- end of auto-generated comment: skip review by coderabbit.ai -->
<!-- tips_start -->

---

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

<details>
<summary>❤️ Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<details>
<summary>🪧 Tips</summary>

### Chat

There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=colinhacks/zod&utm_content=4271):

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
  - `I pushed a fix in commit <commit_id>, please review it.`
  - `Generate unit testing code for this file.`
  - `Open a follow-up GitHub issue for this discussion.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
  - `@coderabbitai generate unit testing code for this file.`
  -	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
  - `@coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.`
  - `@coderabbitai read src/utils.ts and generate unit testing code.`
  - `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`
  - `@coderabbitai help me debug CodeRabbit configuration file.`

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (Invoked using PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai full review` to do a full review from scratch and review all the files again.
- `@coderabbitai summary` to regenerate the summary of the PR.
- `@coderabbitai generate docstrings` to [generate docstrings](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR.
- `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai configuration` to show the current CodeRabbit configuration for the repository.
- `@coderabbitai help` to get help.

### Other keywords and placeholders

- Add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.
- Add `@coderabbitai summary` to generate the high-level summary at a specific location in the PR description.
- Add `@coderabbitai` anywhere in the PR title to generate the title automatically.

### CodeRabbit Configuration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information.
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json`

### Documentation and Community

- Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit.
- Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback.
- Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements.

</details>

<!-- tips_end -->
colinhacks: @coderabbitai review

coderabbitai[bot]: <!-- This is an auto-generated reply by CodeRabbit -->
<details>
<summary>:white_check_mark: Actions performed</summary>

Review triggered.

> Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

</details>

Patch:
diff --git a/biome.jsonc b/biome.jsonc
index 87121a15..3d5977f2 100644
--- a/biome.jsonc
+++ b/biome.jsonc
@@ -3,7 +3,7 @@
   "formatter": {
     "enabled": true,
     "indentStyle": "space",
-    "lineWidth": 120
+    "lineWidth": 80
   },
   "javascript": {
     "formatter": {
diff --git a/packages/core/src/api.ts b/packages/core/src/api.ts
index 8ce68fcb..b6d097a5 100644
--- a/packages/core/src/api.ts
+++ b/packages/core/src/api.ts
@@ -1006,129 +1006,130 @@ export function _array<T extends schemas.$ZodType>(
 }
 
 // ZodObjectLike
-export type $ZodObjectLikeParams = util.TypeParams<schemas.$ZodObjectLike, "shape" | "catchall">;
-
-export type $ZodInterfaceParams = util.TypeParams<schemas.$ZodInterface, "shape">;
-export function _interface<T extends schemas.$ZodLooseShape>(
-  Class: util.SchemaClass<schemas.$ZodInterface>,
-  shape: T,
-  params?: $ZodInterfaceParams
-): schemas.$ZodInterface<util.CleanInterfaceShape<T>, util.InitInterfaceParams<T, {}>> {
-  const cleaned = util.cached(() => util.cleanInterfaceShape(shape));
-  const def: schemas.$ZodInterfaceDef = {
-    type: "interface",
-    get shape() {
-      const _shape = cleaned.value.shape;
-      util.assignProp(this, "shape", _shape);
-      return _shape;
-      // return cleaned.value.shape;
-    },
-    get optional() {
-      return cleaned.value.optional;
-    },
-    ...util.normalizeParams(params),
-  };
-  return new Class(def) as any;
-}
-
-// strictInterface
-export function _strictInterface<T extends schemas.$ZodLooseShape>(
-  Class: util.SchemaClass<schemas.$ZodInterface>,
-  shape: T,
-  params?: $ZodInterfaceParams
-): schemas.$ZodInterface<util.CleanInterfaceShape<T>, util.InitInterfaceParams<T, {}>> {
-  const cleaned = util.cached(() => util.cleanInterfaceShape(shape));
-  const def: schemas.$ZodInterfaceDef = {
-    type: "interface",
-    get shape() {
-      const _shape = cleaned.value.shape;
-      util.assignProp(this, "shape", _shape);
-      return _shape;
-      // return cleaned.value.shape;
-    },
-    get optional() {
-      return cleaned.value.optional;
-    },
-    catchall: _never(schemas.$ZodNever),
-    ...util.normalizeParams(params),
-  };
-  return new Class(def) as any;
-}
-
-// looseInterface
-export function _looseInterface<T extends schemas.$ZodLooseShape>(
-  Class: util.SchemaClass<schemas.$ZodInterface>,
-  shape: T,
-  params?: $ZodInterfaceParams
-): schemas.$ZodInterface<util.CleanInterfaceShape<T>, util.InitInterfaceParams<T, Record<string, unknown>>> {
-  const cleaned = util.cached(() => util.cleanInterfaceShape(shape));
-  const def: schemas.$ZodInterfaceDef = {
-    type: "interface",
-    get optional() {
-      return cleaned.value.optional;
-    },
-    get shape() {
-      const _shape = cleaned.value.shape;
-      util.assignProp(this, "shape", _shape);
-      return _shape;
-      // return cleaned.value.shape;
-    },
-    catchall: _unknown(schemas.$ZodUnknown),
-    ...util.normalizeParams(params),
-  };
-  return new Class(def) as any;
-}
+export type $ZodObjectLikeParams = util.TypeParams<schemas.$ZodObject, "shape" | "catchall">;
+
+// export type $ZodInterfaceParams = util.TypeParams<schemas.$ZodInterface, "shape">;
+// export function _interface<T extends schemas.$ZodLooseShape>(
+//   Class: util.SchemaClass<schemas.$ZodInterface>,
+//   shape: T,
+//   params?: $ZodInterfaceParams
+// ): schemas.$ZodInterface<T, {}> {
+//   const cleaned = util.cached(() => util.cleanInterfaceShape(shape));
+//   const def: schemas.$ZodInterfaceDef = {
+//     type: "interface",
+//     get shape() {
+//       const _shape = cleaned.value.shape;
+//       util.assignProp(this, "shape", _shape);
+//       return _shape;
+//       // return cleaned.value.shape;
+//     },
+//     // get shapeMeta() {
+//     //   return cleaned.value.shapeMeta;
+//     // },
+//     ...util.normalizeParams(params),
+//   };
+//   return new Class(def) as any;
+// }
+
+// // strictInterface
+// export function _strictInterface<T extends schemas.$ZodLooseShape>(
+//   Class: util.SchemaClass<schemas.$ZodInterface>,
+//   shape: T,
+//   params?: $ZodInterfaceParams
+// ): schemas.$ZodInterface<T, {}> {
+//   const cleaned = util.cached(() => util.cleanInterfaceShape(shape));
+//   const def: schemas.$ZodInterfaceDef = {
+//     type: "interface",
+//     get shape() {
+//       const _shape = cleaned.value.shape;
+//       util.assignProp(this, "shape", _shape);
+//       return _shape;
+//       // return cleaned.value.shape;
+//     },
+//     // get shapeMeta() {
+//     //   return cleaned.value.shapeMeta;
+//     // },
+//     catchall: _never(schemas.$ZodNever),
+//     ...util.normalizeParams(params),
+//   };
+//   return new Class(def) as any;
+// }
+
+// // looseInterface
+// export function _looseInterface<T extends schemas.$ZodLooseShape>(
+//   Class: util.SchemaClass<schemas.$ZodInterface>,
+//   shape: T,
+//   params?: string | $ZodInterfaceParams
+// ): schemas.$ZodInterface<T, Record<string, unknown>> {
+//   const cleaned = util.cached(() => util.cleanInterfaceShape(shape));
+//   const def: schemas.$ZodInterfaceDef = {
+//     type: "interface",
+
+//     get shape() {
+//       const _shape = cleaned.value.shape;
+//       util.assignProp(this, "shape", _shape);
+//       return _shape;
+//       // return cleaned.value.shape;
+//     },
+//     // get shapeMeta() {
+//     //   return cleaned.value.shapeMeta;
+//     // },
+//     catchall: _unknown(schemas.$ZodUnknown),
+//     ...util.normalizeParams(params),
+//   };
+//   return new Class(def) as any;
+// }
 
 export type $ZodObjectParams = util.TypeParams<schemas.$ZodObject, "shape" | "catchall">;
-export function _object<T extends schemas.$ZodShape = Record<never, schemas.$ZodObject>>(
-  Class: util.SchemaClass<schemas.$ZodObject>,
-  shape?: T,
-  params?: $ZodObjectLikeParams
-): schemas.$ZodObject<T, {}> {
-  const def: schemas.$ZodObjectDef = {
-    type: "object",
-    shape: shape ?? {},
-    get optional() {
-      return util.optionalObjectKeys(shape ?? {});
-    },
-    ...util.normalizeParams(params),
-  };
-  return new Class(def) as any;
-}
-
-// strictObject
-export function _strictObject<T extends schemas.$ZodShape>(
-  Class: util.SchemaClass<schemas.$ZodObject>,
-  shape: T,
-  params?: $ZodObjectParams
-): schemas.$ZodObject<T, {}> {
-  return new Class({
-    type: "object",
-    shape: shape as schemas.$ZodShape,
-    get optional() {
-      return util.optionalObjectKeys(shape);
-    },
-    catchall: _never(schemas.$ZodNever),
-    ...util.normalizeParams(params),
-  }) as any;
-}
+// export function _object<T extends schemas.$ZodShape = Record<never, schemas.$ZodObject>>(
+//   Class: util.SchemaClass<schemas.$ZodObject>,
+//   shape?: T,
+//   params?: $ZodObjectLikeParams
+// ): schemas.$ZodObject<T, {}> {
+//   const def: schemas.$ZodObjectDef = {
+//     type: "object",
+//     // shape: shape ?? {},
+//     get shape() {
+//       return util.objectShapeMeta(shape ?? {});
+//     },
+//     ...util.normalizeParams(params),
+//   };
+//   return new Class(def) as any;
+// }
 
-// looseObject
-export function _looseObject<T extends schemas.$ZodShape>(
-  Class: util.SchemaClass<schemas.$ZodObject>,
-  shape: T,
-  params?: $ZodObjectParams
-): schemas.$ZodObject<T, { [k: string]: unknown }> {
-  return new Class({
-    type: "object",
-    shape: shape as schemas.$ZodShape,
-    get optional() {
-      return util.optionalObjectKeys(shape);
-    },
-    catchall: _unknown(schemas.$ZodUnknown),
-    ...util.normalizeParams(params),
-  }) as any;
-}
+// // strictObject
+// export function _strictObject<T extends schemas.$ZodShape>(
+//   Class: util.SchemaClass<schemas.$ZodObject>,
+//   shape: T,
+//   params?: $ZodObjectParams
+// ): schemas.$ZodObject<T, {}> {
+//   return new Class({
+//     type: "object",
+//     // shape: shape as schemas.$ZodShape,
+//     get shape() {
+//       return util.objectShapeMeta(shape ?? {});
+//     },
+//     catchall: _never(schemas.$ZodNever),
+//     ...util.normalizeParams(params),
+//   }) as any;
+// }
+
+// // looseObject
+// export function _looseObject<T extends schemas.$ZodShape>(
+//   Class: util.SchemaClass<schemas.$ZodObject>,
+//   shape: T,
+//   params?: $ZodObjectParams
+// ): schemas.$ZodObject<T, { [k: string]: unknown }> {
+//   return new Class({
+//     type: "object",
+//     // shape: shape as schemas.$ZodShape,
+//     get shape() {
+//       return util.objectShapeMeta(shape ?? {});
+//     },
+//     catchall: _unknown(schemas.$ZodUnknown),
+//     ...util.normalizeParams(params),
+//   }) as any;
+// }
 
 // ZodUnion
 export type $ZodUnionParams = util.TypeParams<schemas.$ZodUnion, "options">;
diff --git a/packages/core/src/core.ts b/packages/core/src/core.ts
index 512cd2fe..ea17c872 100644
--- a/packages/core/src/core.ts
+++ b/packages/core/src/core.ts
@@ -1,6 +1,5 @@
 import type * as errors from "./errors.js";
 import type * as schemas from "./schemas.js";
-
 //////////////////////////////   CONSTRUCTORS   ///////////////////////////////////////
 
 type ZodTrait = { _zod: { def: any; [k: string]: any } };
@@ -59,8 +58,12 @@ export class $ZodAsyncError extends Error {
 
 ////////////////////////////  TYPE HELPERS  ///////////////////////////////////
 
-export type input<T extends schemas.$ZodType> = T["_zod"]["input"];
-export type output<T extends schemas.$ZodType> = T["_zod"]["output"];
+export type input<T extends schemas.$ZodType> = T["_zod"] extends { "~input": any }
+  ? T["_zod"]["~input"]
+  : T["_zod"]["input"];
+export type output<T extends schemas.$ZodType> = T["_zod"] extends { "~output": any }
+  ? T["_zod"]["~output"]
+  : T["_zod"]["output"];
 export type { output as infer };
 
 //////////////////////////////   CONFIG   ///////////////////////////////////////
diff --git a/packages/core/src/json-schema.ts b/packages/core/src/json-schema.ts
index 486a3ac7..6ca2d6e1 100644
--- a/packages/core/src/json-schema.ts
+++ b/packages/core/src/json-schema.ts
@@ -11,7 +11,6 @@ export type Schema =
 export interface BaseSchema {
   /** A special key used as an intermediate representation of extends-style relationships. Removed in the omit stage. */
   _ref?: BaseSchema;
-
   type?: string | undefined;
   $id?: string | undefined;
   id?: string | undefined;
diff --git a/packages/core/src/schemas.ts b/packages/core/src/schemas.ts
index 5d642ed3..c925e9f9 100644
--- a/packages/core/src/schemas.ts
+++ b/packages/core/src/schemas.ts
@@ -79,21 +79,31 @@ export interface $ZodTypeDef {
   checks?: checks.$ZodCheck<never>[];
 }
 
-export interface $ZodTypeInternals<out O = unknown, out I = unknown> extends $ZodType<O, I> {
+export const $out: unique symbol = Symbol("out");
+export type $out = typeof $out;
+export const $in: unique symbol = Symbol("in");
+export type $in = typeof $in;
+
+// @ts-ignore
+export interface $ZodTypeInternals<out O = unknown, out I = unknown> {
   /** The `@zod/core` version of this schema */
   version: typeof version;
 
   /** Schema internals. */
   def: $ZodTypeDef;
+  // types: Types;
 
   /** Randomly generated ID for this schema. */
   id: string;
 
-  /** The inferred output typre */
-  output: O;
-
+  /** The inferred output type */
+  // "
+  // "?: any;
+  // "~input"?: any;
+  // "~types"?: any;
+  output: O; //extends { $out: infer O } ? O : Out;
   /** The inferred input type */
-  input: I;
+  input: I; //extends { $in: infer I } ? I : In;
 
   /** List of deferred initializers. */
   deferred: util.AnyFunc[] | undefined;
@@ -107,11 +117,10 @@ export interface $ZodTypeInternals<out O = unknown, out I = unknown> extends $Zo
   /** Stores identifiers for the set of traits implemented by this schema. */
   traits: Set<string>;
 
-  /** Indicates that a schema output type should be considered optional inside objects.  */
-  qout: "true" | undefined;
-
-  /** Indicates that a schema input type should be considered optional inside objects. */
-  qin: "true" | undefined;
+  /** Indicates that a schema output type should be considered optional inside objects.
+   * @default Required
+   */
+  optionality?: "optional" | "defaulted" | undefined;
 
   /** A set of literal discriminators used for the fast path in discriminated unions. */
   disc: util.DiscriminatorMap | undefined;
@@ -145,9 +154,20 @@ export interface $ZodTypeInternals<out O = unknown, out I = unknown> extends $Zo
   parent?: $ZodType | undefined;
 }
 
-export interface $ZodType<out O = unknown, out I = unknown> {
+// export interface $ZodTypeInternals<out O = unknown, out I = unknown> extends $ZodTypeInternals {
+//   // "~types": { output: O; input: I };
+//   output: O;
+//   input: I;
+// }
+
+// export interface _$ZodType {
+//   _zod: $ZodTypeInternals;
+//   "~standard": StandardSchemaV1.Props<core.input<this>, core.output<this>>;
+// }
+
+export interface $ZodType<O = unknown, I = unknown> {
   _zod: $ZodTypeInternals<O, I>;
-  "~standard": StandardSchemaV1.Props<this["_zod"]["input"], this["_zod"]["output"]>;
+  "~standard": StandardSchemaV1.Props<core.input<this>, core.output<this>>;
 }
 
 export const $ZodType: core.$constructor<$ZodType> = /*@__PURE__*/ core.$constructor("$ZodType", (inst, def) => {
@@ -156,9 +176,9 @@ export const $ZodType: core.$constructor<$ZodType> = /*@__PURE__*/ core.$constru
   inst._zod.def = def; // set _def property
   inst._zod.computed = inst._zod.computed || {}; // initialize _computed object
   inst._zod.version = version;
+  // inst._zod.optionality ??= "required"; // default
 
   const checks = [...(inst._zod.def.checks ?? [])];
-  def.type;
 
   // if inst is itself a checks.$ZodCheck, run it as a check
   if (inst._zod.traits.has("$ZodCheck")) {
@@ -1387,7 +1407,7 @@ export interface $ZodArrayDef<T extends $ZodType = $ZodType> extends $ZodTypeDef
 }
 
 export interface $ZodArrayInternals<T extends $ZodType = $ZodType>
-  extends $ZodTypeInternals<T["_zod"]["output"][], T["_zod"]["input"][]> {
+  extends $ZodTypeInternals<core.output<T>[], core.input<T>[]> {
   def: $ZodArrayDef<T>;
   isst: errors.$ZodIssueInvalidType;
 }
@@ -1423,7 +1443,6 @@ export const $ZodArray: core.$constructor<$ZodArray> = /*@__PURE__*/ core.$const
     const proms: Promise<any>[] = [];
     for (let i = 0; i < input.length; i++) {
       const item = input[i];
-
       const result = def.element._zod.run(
         {
           value: item,
@@ -1450,29 +1469,70 @@ export const $ZodArray: core.$constructor<$ZodArray> = /*@__PURE__*/ core.$const
 //////////////////////////////////////////
 //////////////////////////////////////////
 //////////                      //////////
-//////////      $ZodObjectLike      //////////
+//////////      $ZodObject      //////////
 //////////                      //////////
 //////////////////////////////////////////
 //////////////////////////////////////////
 
 export type $ZodShape = Readonly<{ [k: string]: $ZodType }>;
+// export type $ZodShapeMetaValue<T extends $ZodType = $ZodType> = {
+//   type: T;
+//   optionality?: "optional" | "defaulted" | undefined;
+// };
+// export type $ZodShapeMeta<T extends $ZodShape = $ZodShape> = Readonly<{ [k in keyof T]: $ZodShapeMetaValue<T[k]> }>;
 
-export interface $ZodObjectLikeDef<out Shape extends $ZodShape = $ZodShape> extends $ZodTypeDef {
-  type: "object" | "interface";
+export interface $ZodObjectDef<Shape extends $ZodShape = $ZodShape> extends $ZodTypeDef {
+  type: "object";
   shape: Shape;
-  optional: string[];
   catchall?: $ZodType | undefined;
 }
 
-export interface $ZodObjectLikeInternals<out O = object, out I = object> extends $ZodTypeInternals<O, I> {
-  def: $ZodObjectLikeDef;
-  // shape: $ZodShape;
-  extra: Record<string, unknown>;
-  optional: string;
-  defaulted: string;
+export interface $ZodObjectInternals<
+  Shape extends Readonly<$ZodShape> = Readonly<$ZodShape>,
+  out OutExtra extends Record<string, unknown> = Record<string, unknown>,
+  out InExtra extends Record<string, unknown> = Record<string, unknown>,
+> extends $ZodTypeInternals<any, any> {
+  def: $ZodObjectDef<Shape>;
+  outextra: OutExtra;
+  inextra: InExtra;
   isst: errors.$ZodIssueInvalidType | errors.$ZodIssueUnrecognizedKeys;
   disc: util.DiscriminatorMap;
+
+  // special keys only used for objects
+  // not defined on $ZodTypeInternals (base interface) because it breaks cyclical inference
+  // the z.infer<> util checks for these first when extracting inferred type
+  "~output": $InferObjectOutput<Shape, OutExtra>;
+  "~input": $InferObjectInput<Shape, InExtra>;
 }
+export type $ZodLooseShape = Record<string, any>;
+
+type OptionalOutSchema = { _zod: { optionality: "optional" } };
+type OptionalInSchema = { _zod: { optionality: "defaulted" | "optional" } };
+
+export type $InferObjectOutput<T extends $ZodLooseShape, Extra extends Record<string, unknown>> = string extends keyof T
+  ? object
+  : keyof T extends never
+    ? object
+    : util.Prettify<
+        {
+          -readonly [k in keyof T as T[k] extends OptionalOutSchema ? never : k]: core.output<T[k]>;
+        } & {
+          -readonly [k in keyof T as T[k] extends OptionalOutSchema ? k : never]?: core.output<T[k]>;
+        }
+      > &
+        Extra;
+
+export type $InferObjectInput<T extends $ZodLooseShape, Extra extends Record<string, unknown>> = string extends keyof T
+  ? object
+  : keyof T extends never
+    ? object
+    : util.Prettify<
+        {
+          [k in keyof T as T[k] extends OptionalInSchema ? never : k]: core.input<T[k]>;
+        } & {
+          [k in keyof T as T[k] extends OptionalInSchema ? k : never]?: core.input<T[k]>;
+        } & Extra
+      >;
 
 function handleObjectResult(result: ParsePayload, final: ParsePayload, key: PropertyKey) {
   // if(isOptional)
@@ -1503,145 +1563,96 @@ function handleOptionalObjectResult(result: ParsePayload, final: ParsePayload, k
   }
 }
 
-export interface $ZodObjectLike<O = object, I = object> extends $ZodType {
-  _zod: $ZodObjectLikeInternals<O, I>;
+export interface $ZodObject<
+  Shape extends Readonly<$ZodShape> = Readonly<$ZodShape>,
+  OutExtra extends Record<string, unknown> = Record<string, unknown>,
+  InExtra extends Record<string, unknown> = Record<string, unknown>,
+> extends $ZodType {
+  _zod: $ZodObjectInternals<Shape, OutExtra, InExtra>;
 }
 
-export const $ZodObjectLike: core.$constructor<$ZodObjectLike> = /*@__PURE__*/ core.$constructor(
-  "$ZodObjectLike",
-  (inst, def) => {
-    $ZodType.init(inst, def);
-    // util.defineLazy(inst._zod, "shape", () => def.shape);
-
-    const _normalized = util.cached(() => {
-      const keys = Object.keys(def.shape);
-      return {
-        shape: def.shape,
-        keys,
-        keySet: new Set(keys),
-        numKeys: keys.length,
-        optionalKeys: new Set(def.optional),
-      };
-    });
+export const $ZodObject: core.$constructor<$ZodObject> = /*@__PURE__*/ core.$constructor("$ZodObject", (inst, def) => {
+  $ZodType.init(inst, def);
+  // util.defineLazy(inst._zod, "shape", () => def.shape);
+
+  const _normalized = util.cached(() => {
+    const keys = Object.keys(def.shape);
+    const okeys = util.optionalObjectKeys(def.shape);
+    return {
+      shape: def.shape,
+      keys,
+      keySet: new Set(keys),
+      numKeys: keys.length,
+      optionalKeys: new Set(okeys),
+    };
+  });
 
-    util.defineLazy(inst._zod, "disc", () => {
-      const shape = def.shape;
-      const discMap: util.DiscriminatorMap = new Map();
-      let hasDisc = false;
-      for (const key in shape) {
-        const field = shape[key]._zod;
-        if (field.values || field.disc) {
-          hasDisc = true;
-          const o: util.DiscriminatorMapElement = {
-            values: new Set(field.values ?? []),
-            maps: field.disc ? [field.disc] : [],
-          };
-          discMap.set(key, o);
-        }
-      }
-      if (!hasDisc) {
-        return undefined as any;
+  util.defineLazy(inst._zod, "disc", () => {
+    const shape = def.shape;
+    const discMap: util.DiscriminatorMap = new Map();
+    let hasDisc = false;
+    for (const key in shape) {
+      const field = shape[key]._zod;
+      if (field.values || field.disc) {
+        hasDisc = true;
+        const o: util.DiscriminatorMapElement = {
+          values: new Set(field.values ?? []),
+          maps: field.disc ? [field.disc] : [],
+        };
+        discMap.set(key, o);
       }
-      return discMap;
-    });
+    }
+    if (!hasDisc) {
+      return undefined as any;
+    }
+    return discMap;
+  });
 
-    const generateFastpass = (shape: any) => {
-      const doc = new Doc(["shape", "payload", "ctx"]);
-      const { keys, optionalKeys } = _normalized.value;
-      const parseStr = (key: string) => {
-        const k = util.esc(key);
-        return `shape[${k}]._zod.run({ value: input[${k}], issues: [] }, ctx)`;
-      };
+  const generateFastpass = (shape: any) => {
+    const doc = new Doc(["shape", "payload", "ctx"]);
+    const { keys, optionalKeys } = _normalized.value;
 
-      // doc.write(`const shape = inst._zod.def.shape;`);
-      doc.write(`const input = payload.value;`);
+    const parseStr = (key: string) => {
+      const k = util.esc(key);
+      return `shape[${k}]._zod.run({ value: input[${k}], issues: [] }, ctx)`;
+    };
 
-      const ids: any = {};
-      for (const key of keys) {
-        ids[key] = util.randomString(15);
-      }
-      for (const key of keys) {
-        if (optionalKeys.has(key)) continue;
-        const id = ids[key];
-        doc.write(`const ${id} = ${parseStr(key)};`);
-        doc.write(`
+    // doc.write(`const shape = inst._zod.def.shape;`);
+    doc.write(`const input = payload.value;`);
+
+    const ids: any = {};
+    for (const key of keys) {
+      ids[key] = util.randomString(15);
+    }
+    for (const key of keys) {
+      if (optionalKeys.has(key)) continue;
+      const id = ids[key];
+      doc.write(`const ${id} = ${parseStr(key)};`);
+      doc.write(`
           if (${id}.issues.length) payload.issues = payload.issues.concat(${id}.issues.map(iss => ({
             ...iss,
             path: iss.path ? [${util.esc(key)}, ...iss.path] : [${util.esc(key)}]
           })));`);
-      }
+    }
 
-      // check for missing keys
-      // for (const key of keys) {
-      //   if (optionalKeys.has(key)) continue;
-      //   doc.write(`if(!(${util.esc(key)} in input)) {`);
-      //   doc.indented(() => {
-      //     doc.write(`payload.issues.push({`);
-      //     doc.indented(() => {
-      //       doc.write(`code: "invalid_type",`);
-      //       doc.write(`path: [${util.esc(key)}],`);
-      //       doc.write(`expected: "nonoptional",`);
-      //       doc.write(`note: 'Missing required key: "${key}"',`);
-      //       doc.write(`input,`);
-      //       doc.write(`inst,`);
-      //     });
-      //     doc.write(`});`);
-      //   });
-      //   doc.write(`}`);
-      // }
-
-      // add required keys to result
-      // doc.write(`return payload;`);
-      // doc.write(`if(Object.keys(input).length === ${keys.length}) {
-      //   payload.value = {...input};
-      //   return payload;
-      // }`);
-      doc.write(`payload.value = {`);
-      doc.indented(() => {
-        for (const key of keys) {
-          if (optionalKeys.has(key)) continue;
-          const id = ids[key];
-          doc.write(`  ${util.esc(key)}: ${id}.value,`);
-          // doc.write(`payload.value[${util.esc(key)}] = ${id}.value;`);
-        }
-      });
-      doc.write(`}`);
-
-      // add in optionalKeys if defined
-
-      // OLD: only run validation if they are define in input
-      // for (const key of keys) {
-      //   if (!optionalKeys.has(key)) continue;
-      //   const id = ids[key];
-      //   doc.write(`if (${util.esc(key)} in input) {`);
-      //   doc.indented(() => {
-      //     doc.write(`if(input[${util.esc(key)}] === undefined) {`);
-      //     doc.indented(() => {
-      //       doc.write(`payload.value[${util.esc(key)}] = undefined;`);
-      //     });
-      //     doc.write(`} else {`);
-      //     doc.indented(() => {
-      //       doc.write(`const ${id} = ${parseStr(key)};`);
-      //       doc.write(`payload.value[${util.esc(key)}] = ${id}.value;`);
-      //       doc.write(`
-      //         if (${id}.issues.length) payload.issues = payload.issues.concat(${id}.issues.map(iss => ({
-      //           ...iss,
-      //           path: iss.path ? [${util.esc(key)}, ...iss.path] : [${util.esc(key)}]
-      //         })));`);
-      //     });
-      //     doc.write(`}`);
-      //   });
-      //   doc.write(`}`);
-      // }
-
-      // NEW: always run validation
-      // this lets default values get applied to optionals
+    doc.write(`payload.value = {`);
+    doc.indented(() => {
       for (const key of keys) {
-        if (!optionalKeys.has(key)) continue;
+        if (optionalKeys.has(key)) continue;
         const id = ids[key];
-        doc.write(`const ${id} = ${parseStr(key)};`);
-        const k = util.esc(key);
-        doc.write(`
+        doc.write(`  ${util.esc(key)}: ${id}.value,`);
+      }
+    });
+    doc.write(`}`);
+
+    // NEW: always run validation
+    // this lets default values get applied to optionals
+    for (const key of keys) {
+      if (!optionalKeys.has(key)) continue;
+      const id = ids[key];
+      doc.write(`const ${id} = ${parseStr(key)};`);
+      const k = util.esc(key);
+      doc.write(`
         if (${id}.issues.length) {
           if (input[${k}] === undefined) {
             if (${k} in input) {
@@ -1661,268 +1672,116 @@ export const $ZodObjectLike: core.$constructor<$ZodObjectLike> = /*@__PURE__*/ c
           payload.value[${k}] = ${id}.value;
         }  
         `);
-      }
+    }
 
-      // doc.write(`payload.value = final;`);
-      doc.write(`return payload;`);
-      // return doc.compile().bind(null, shape);
-      const fn = doc.compile();
-      return (payload: any, ctx: any) => fn(shape, payload, ctx);
-      // return fn.bind(null, _inst._zod.def.shape);
-    };
+    doc.write(`return payload;`);
+    const fn = doc.compile();
+    return (payload: any, ctx: any) => fn(shape, payload, ctx);
+  };
 
-    let fastpass!: ReturnType<typeof generateFastpass>;
-    const fastEnabled = util.allowsEval.value; // && !def.catchall;
-    const isObject = util.isObject;
-    const { catchall } = def;
+  let fastpass!: ReturnType<typeof generateFastpass>;
+  const fastEnabled = util.allowsEval.value; // && !def.catchall;
+  const isObject = util.isObject;
+  const { catchall } = def;
 
-    let value!: typeof _normalized.value;
+  let value!: typeof _normalized.value;
 
-    // const noCatchall = !def.catchall;
+  inst._zod.parse = (payload, ctx) => {
+    value ??= _normalized.value;
+    const input = payload.value;
+    if (!isObject(input)) {
+      payload.issues.push({
+        expected: "object",
+        code: "invalid_type",
+        input,
+        inst,
+      });
+      return payload;
+    }
 
-    inst._zod.parse = (payload, ctx) => {
-      value ??= _normalized.value;
-      const input = payload.value;
-      if (!isObject(input)) {
-        payload.issues.push({
-          expected: "object",
-          code: "invalid_type",
-          input,
-          inst,
-        });
-        return payload;
-      }
+    const proms: Promise<any>[] = [];
 
-      const proms: Promise<any>[] = [];
+    if (fastEnabled && ctx?.async === false && ctx.noPrecompilation !== true) {
+      // always synchronous
+      if (!fastpass) fastpass = generateFastpass(def.shape);
+      payload = fastpass(payload, ctx);
+    } else {
+      payload.value = {};
 
-      if (fastEnabled && ctx?.async === false && ctx.noPrecompilation !== true) {
-        // always synchronous
-        if (!fastpass) fastpass = generateFastpass(def.shape);
-        payload = fastpass(payload, ctx);
-      } else {
-        payload.value = {};
-        // const normalized = _normalized.value;
-        const { keys, shape, optionalKeys } = value;
-        for (const key of keys) {
-          const valueSchema = shape[key];
-
-          // do not add omitted optional keys
-          // if (!(key in input)) {
-          //   if (optionalKeys.has(key)) continue;
-          //   payload.issues.push({
-          //     code: "invalid_type",
-          //     path: [key],
-          //     expected: "nonoptional",
-          //     note: `Missing required key: "${key}"`,
-          //     input,
-          //     inst,
-          //   });
-          // }
-
-          const r = valueSchema._zod.run({ value: input[key], issues: [] }, ctx);
-          const isOptional = optionalKeys.has(key);
-          // if (isOptional) {
-          //   if (!(key in input)) {
-          //     continue;
-          //   }
-          //   if (input[key] === undefined) {
-          //     input[key] = undefined;
-          //     continue;
-          //   }
-          // }
-
-          // const r = valueSchema._zod.run({ value: input[key], issues: [] }, ctx);
-          if (r instanceof Promise) {
-            proms.push(
-              r.then((r) =>
-                isOptional ? handleOptionalObjectResult(r, payload, key, input) : handleObjectResult(r, payload, key)
-              )
-            );
+      const shape = value.shape;
+      for (const key of value.keys) {
+        const el = shape[key];
+
+        // do not add omitted optional keys
+        // if (!(key in input)) {
+        //   if (optionalKeys.has(key)) continue;
+        //   payload.issues.push({
+        //     code: "invalid_type",
+        //     path: [key],
+        //     expected: "nonoptional",
+        //     note: `Missing required key: "${key}"`,
+        //     input,
+        //     inst,
+        //   });
+        // }
+
+        const r = el._zod.run({ value: input[key], issues: [] }, ctx);
+        const isOptional = el._zod.optionality === "optional";
+
+        if (r instanceof Promise) {
+          proms.push(
+            r.then((r) =>
+              isOptional ? handleOptionalObjectResult(r, payload, key, input) : handleObjectResult(r, payload, key)
+            )
+          );
+        } else {
+          if (isOptional) {
+            handleOptionalObjectResult(r, payload, key, input);
           } else {
-            if (isOptional) {
-              handleOptionalObjectResult(r, payload, key, input);
-            } else {
-              handleObjectResult(r, payload, key);
-            }
+            handleObjectResult(r, payload, key);
           }
         }
       }
+    }
 
-      if (!catchall) {
-        // return payload;
-        return proms.length ? Promise.all(proms).then(() => payload) : payload;
-      }
-      const unrecognized: string[] = [];
-      // iterate over input keys
-      const keySet = value.keySet;
-      const _catchall = catchall._zod;
-      const t = _catchall.def.type;
-      for (const key of Object.keys(input)) {
-        if (keySet.has(key)) continue;
-        if (t === "never") {
-          unrecognized.push(key);
-          continue;
-        }
-        const r = _catchall.run({ value: input[key], issues: [] }, ctx);
-
-        if (r instanceof Promise) {
-          proms.push(r.then((r) => handleObjectResult(r, payload, key)));
-        } else {
-          handleObjectResult(r, payload, key);
-        }
+    if (!catchall) {
+      // return payload;
+      return proms.length ? Promise.all(proms).then(() => payload) : payload;
+    }
+    const unrecognized: string[] = [];
+    // iterate over input keys
+    const keySet = value.keySet;
+    const _catchall = catchall._zod;
+    const t = _catchall.def.type;
+    for (const key of Object.keys(input)) {
+      if (keySet.has(key)) continue;
+      if (t === "never") {
+        unrecognized.push(key);
+        continue;
       }
+      const r = _catchall.run({ value: input[key], issues: [] }, ctx);
 
-      if (unrecognized.length) {
-        payload.issues.push({
-          code: "unrecognized_keys",
-          keys: unrecognized,
-          input,
-          inst,
-        });
+      if (r instanceof Promise) {
+        proms.push(r.then((r) => handleObjectResult(r, payload, key)));
+      } else {
+        handleObjectResult(r, payload, key);
       }
+    }
 
-      if (!proms.length) return payload;
-      return Promise.all(proms).then(() => {
-        return payload;
+    if (unrecognized.length) {
+      payload.issues.push({
+        code: "unrecognized_keys",
+        keys: unrecognized,
+        input,
+        inst,
       });
-    };
-  }
-);
-
-///////////////////////////////////////////////////
-/////////////      $ZodInterface      /////////////
-///////////////////////////////////////////////////
-// looser type is required for recursive inference
-export type $ZodLooseShape = Record<string, any>;
-
-export type $InferInterfaceOutput<
-  T extends $ZodLooseShape,
-  Params extends $ZodInterfaceNamedParams,
-> = string extends keyof T
-  ? object
-  : {} extends T
-    ? object
-    : util.Flatten<
-        {
-          -readonly [k in Params["optional"]]?: T[k]["_zod"]["output"];
-        } & {
-          -readonly [k in Exclude<keyof T, Params["optional"]>]: T[k]["_zod"]["output"];
-        } & Params["extra"]
-      >;
-
-export type $InferInterfaceInput<
-  T extends $ZodLooseShape,
-  Params extends $ZodInterfaceNamedParams,
-> = string extends keyof T
-  ? Record<string, unknown>
-  : $ZodInterfaceNamedParams extends Params
-    ? Record<string, unknown>
-    : util.Flatten<
-        {
-          -readonly [k in Params["optional"] | Params["defaulted"]]?: T[k]["_zod"]["input"];
-        } & {
-          -readonly [k in Exclude<keyof T, Params["optional"] | Params["defaulted"]>]: T[k]["_zod"]["input"];
-        } & Params["extra"]
-      >;
-
-export interface $ZodInterfaceDef<out Shape extends $ZodLooseShape = $ZodLooseShape> extends $ZodObjectLikeDef<Shape> {
-  type: "interface";
-}
-
-export interface $ZodInterfaceNamedParams {
-  optional: string;
-  defaulted: string;
-  extra: Record<string, unknown>;
-}
-
-export interface $ZodInterfaceInternals<
-  Shape extends Readonly<$ZodLooseShape> = Readonly<$ZodLooseShape>,
-  Params extends $ZodInterfaceNamedParams = $ZodInterfaceNamedParams,
-> extends $ZodObjectLikeInternals<$InferInterfaceOutput<Shape, Params>, $InferInterfaceInput<Shape, Params>> {
-  subtype: "interface";
-  def: $ZodInterfaceDef<Shape>;
-  // shape: Shape;
-  optional: Params["optional"];
-  defaulted: Params["defaulted"];
-  extra: Params["extra"];
-}
-
-export interface $ZodInterface<
-  Shape extends Readonly<$ZodLooseShape> = Readonly<$ZodLooseShape>,
-  Params extends $ZodInterfaceNamedParams = {
-    optional: string;
-    defaulted: string;
-    extra: Record<string, unknown>;
-  },
-> extends $ZodType {
-  _zod: $ZodInterfaceInternals<Shape, Params>;
-}
-
-export const $ZodInterface: core.$constructor<$ZodInterface> = /*@__PURE__*/ core.$constructor(
-  "$ZodInterface",
-  (inst, def) => {
-    $ZodObjectLike.init(inst, def);
-  }
-);
-
-///////////////////////////////////////////////////////
-/////////////      $ZodObject      /////////////
-///////////////////////////////////////////////////////
-
-// compute output type
-type OptionalOutKeys<T extends $ZodShape> = {
-  [k in keyof T]: T[k] extends { _zod: { qout: "true" } } ? k : never;
-}[keyof T];
-type OptionalOutProps<T extends $ZodShape> = {
-  [k in OptionalOutKeys<T>]?: T[k]["_zod"]["output"];
-};
-type RequiredOutProps<T extends $ZodShape> = {
-  [k in keyof T as T[k]["_zod"]["qout"] extends "true" ? never : k]-?: T[k]["_zod"]["output"];
-};
-export type $InferObjectOutput<T extends $ZodShape, Extra extends Record<string, unknown>> = {} extends T
-  ? object
-  : util.Flatten<OptionalOutProps<T> & RequiredOutProps<T>> & Extra;
-
-// compute input type
-type OptionalInKeys<T extends $ZodShape> = {
-  [k in keyof T]: T[k] extends { _zod: { qin: "true" } } ? k : never;
-}[keyof T];
-type OptionalInProps<T extends $ZodShape> = {
-  [k in OptionalInKeys<T>]?: T[k]["_zod"]["input"];
-};
-type RequiredInKeys<T extends $ZodShape> = {
-  [k in keyof T]: T[k] extends { _zod: { qin: "true" } } ? never : k;
-}[keyof T];
-type RequiredInProps<T extends $ZodShape> = {
-  [k in RequiredInKeys<T>]: T[k]["_zod"]["input"];
-};
-export type $InferObjectInput<T extends $ZodShape, Extra extends Record<string, unknown>> = util.Flatten<
-  ({} extends T ? object : OptionalInProps<T> & RequiredInProps<T>) & Extra
->;
-
-export interface $ZodObjectDef<Shape extends $ZodShape = $ZodShape> extends $ZodObjectLikeDef<Shape> {
-  type: "object";
-  shape: Shape;
-}
-
-export interface $ZodObjectInternals<
-  Shape extends $ZodShape = $ZodShape,
-  Extra extends Record<string, unknown> = Record<string, unknown>,
-> extends $ZodObjectLikeInternals<$InferObjectOutput<Shape, Extra>, $InferObjectInput<Shape, Extra>> {
-  subtype: "object";
-  def: $ZodObjectDef<Shape>;
-  extra: Extra;
-}
-
-export interface $ZodObject<
-  Shape extends $ZodShape = $ZodShape,
-  Extra extends Record<string, unknown> = Record<string, unknown>,
-> extends $ZodType {
-  _zod: $ZodObjectInternals<Shape, Extra>;
-}
+    }
 
-export const $ZodObject: core.$constructor<$ZodObject> = /*@__PURE__*/ core.$constructor("$ZodObject", (inst, def) => {
-  $ZodObjectLike.init(inst, def);
+    if (!proms.length) return payload;
+    return Promise.all(proms).then(() => {
+      return payload;
+    });
+  };
 });
 
 /////////////////////////////////////////
@@ -1938,7 +1797,7 @@ export interface $ZodUnionDef<Options extends readonly $ZodType[] = readonly $Zo
 }
 
 export interface $ZodUnionInternals<T extends readonly $ZodType[] = readonly $ZodType[]>
-  extends $ZodTypeInternals<T[number]["_zod"]["output"], T[number]["_zod"]["input"]> {
+  extends $ZodTypeInternals<core.output<T[number]>, core.input<T[number]>> {
   def: $ZodUnionDef<T>;
   isst: errors.$ZodIssueInvalidUnion;
   pattern: T[number]["_zod"]["pattern"];
@@ -2145,7 +2004,7 @@ export interface $ZodIntersectionDef extends $ZodTypeDef {
 }
 
 export interface $ZodIntersectionInternals<A extends $ZodType = $ZodType, B extends $ZodType = $ZodType>
-  extends $ZodTypeInternals<A["_zod"]["output"] & B["_zod"]["output"], A["_zod"]["input"] & B["_zod"]["input"]> {
+  extends $ZodTypeInternals<core.output<A> & core.output<B>, core.input<A> & core.input<B>> {
   def: $ZodIntersectionDef;
   isst: never;
 }
@@ -2272,33 +2131,33 @@ export interface $ZodTupleDef<
 
 export type $InferTupleInputType<T extends util.TupleItems, Rest extends $ZodType | null> = [
   ...TupleInputTypeWithOptionals<T>,
-  ...(Rest extends $ZodType ? Rest["_zod"]["input"][] : []),
+  ...(Rest extends $ZodType ? core.input<Rest>[] : []),
 ];
 type TupleInputTypeNoOptionals<T extends util.TupleItems> = {
-  [k in keyof T]: T[k]["_zod"]["input"];
+  [k in keyof T]: core.input<T[k]>;
 };
 type TupleInputTypeWithOptionals<T extends util.TupleItems> = T extends readonly [
   ...infer Prefix extends $ZodType[],
   infer Tail extends $ZodType,
 ]
-  ? Tail["_zod"]["qin"] extends "true"
+  ? Tail["_zod"]["optionality"] extends "optional" | "defaulted"
     ? [...TupleInputTypeWithOptionals<Prefix>, Tail["_zod"]["input"]?]
     : TupleInputTypeNoOptionals<T>
   : [];
 
 export type $InferTupleOutputType<T extends util.TupleItems, Rest extends $ZodType | null> = [
   ...TupleOutputTypeWithOptionals<T>,
-  ...(Rest extends $ZodType ? Rest["_zod"]["output"][] : []),
+  ...(Rest extends $ZodType ? core.output<Rest>[] : []),
 ];
 type TupleOutputTypeNoOptionals<T extends util.TupleItems> = {
-  [k in keyof T]: T[k]["_zod"]["output"];
+  [k in keyof T]: core.output<T[k]>;
 };
 type TupleOutputTypeWithOptionals<T extends util.TupleItems> = T extends readonly [
   ...infer Prefix extends $ZodType[],
   infer Tail extends $ZodType,
 ]
-  ? Tail["_zod"]["qout"] extends "true"
-    ? [...TupleOutputTypeWithOptionals<Prefix>, Tail["_zod"]["output"]?]
+  ? Tail["_zod"]["optionality"] extends "optional"
+    ? [...TupleOutputTypeWithOptionals<Prefix>, core.output<Tail>?]
     : TupleOutputTypeNoOptionals<T>
   : [];
 
@@ -2318,7 +2177,7 @@ export interface $ZodTuple<T extends util.TupleItems = util.TupleItems, Rest ext
 export const $ZodTuple: core.$constructor<$ZodTuple> = /*@__PURE__*/ core.$constructor("$ZodTuple", (inst, def) => {
   $ZodType.init(inst, def);
   const items = def.items;
-  const optStart = items.length - [...items].reverse().findIndex((item) => item._zod.qout !== "true");
+  const optStart = items.length - [...items].reverse().findIndex((item) => item._zod.optionality !== "optional");
 
   inst._zod.parse = (payload, ctx) => {
     const input = payload.value;
@@ -2421,13 +2280,13 @@ type $InferZodRecordOutput<
   Value extends $ZodType = $ZodType,
 > = undefined extends Key["_zod"]["values"]
   ? string extends Key["_zod"]["output"]
-    ? Record<Key["_zod"]["output"], Value["_zod"]["output"]>
+    ? Record<Key["_zod"]["output"], core.output<Value>>
     : number extends Key["_zod"]["output"]
-      ? Record<Key["_zod"]["output"], Value["_zod"]["output"]>
+      ? Record<Key["_zod"]["output"], core.output<Value>>
       : symbol extends Key["_zod"]["output"]
-        ? Record<Key["_zod"]["output"], Value["_zod"]["output"]>
-        : Partial<Record<Key["_zod"]["output"], Value["_zod"]["output"]>>
-  : Record<Key["_zod"]["output"], Value["_zod"]["output"]>;
+        ? Record<Key["_zod"]["output"], core.output<Value>>
+        : Partial<Record<Key["_zod"]["output"], core.output<Value>>>
+  : Record<Key["_zod"]["output"], core.output<Value>>;
 
 type $InferZodRecordInput<
   Key extends $ZodRecordKey = $ZodRecordKey,
@@ -2576,10 +2435,7 @@ export interface $ZodMapDef extends $ZodTypeDef {
 }
 
 export interface $ZodMapInternals<Key extends $ZodType = $ZodType, Value extends $ZodType = $ZodType>
-  extends $ZodTypeInternals<
-    Map<Key["_zod"]["output"], Value["_zod"]["output"]>,
-    Map<Key["_zod"]["input"], Value["_zod"]["input"]>
-  > {
+  extends $ZodTypeInternals<Map<core.output<Key>, core.output<Value>>, Map<core.input<Key>, core.input<Value>>> {
   def: $ZodMapDef;
   isst: errors.$ZodIssueInvalidType | errors.$ZodIssueInvalidKey | errors.$ZodIssueInvalidElement<unknown>;
 }
@@ -2679,7 +2535,7 @@ export interface $ZodSetDef extends $ZodTypeDef {
 }
 
 export interface $ZodSetInternals<T extends $ZodType = $ZodType>
-  extends $ZodTypeInternals<Set<T["_zod"]["output"]>, Set<T["_zod"]["input"]>> {
+  extends $ZodTypeInternals<Set<core.output<T>>, Set<core.input<T>>> {
   def: $ZodSetDef;
   isst: errors.$ZodIssueInvalidType;
 }
@@ -2979,10 +2835,9 @@ export interface $ZodOptionalDef<T extends $ZodType = $ZodType> extends $ZodType
 }
 
 export interface $ZodOptionalInternals<T extends $ZodType = $ZodType>
-  extends $ZodTypeInternals<T["_zod"]["output"] | undefined, T["_zod"]["input"] | undefined> {
+  extends $ZodTypeInternals<core.output<T> | undefined, core.input<T> | undefined> {
   def: $ZodOptionalDef<T>;
-  qin: "true";
-  qout: "true";
+  optionality: "optional";
   isst: never;
   values: T["_zod"]["values"];
   pattern: RegExp;
@@ -2996,8 +2851,9 @@ export const $ZodOptional: core.$constructor<$ZodOptional> = /*@__PURE__*/ core.
   "$ZodOptional",
   (inst, def) => {
     $ZodType.init(inst, def);
+    inst._zod.optionality = "optional";
     // inst._zod.qin = "true";
-    inst._zod.qout = "true";
+    // inst._zod.qout = "true";
     if (def.innerType._zod.values) inst._zod.values = new Set([...def.innerType._zod.values, undefined]);
     const pattern = (def.innerType as any)._zod.pattern;
     if (pattern) inst._zod.pattern = new RegExp(`^(${util.cleanRegex(pattern.source)})?$`);
@@ -3024,10 +2880,9 @@ export interface $ZodNullableDef<T extends $ZodType = $ZodType> extends $ZodType
 }
 
 export interface $ZodNullableInternals<T extends $ZodType = $ZodType>
-  extends $ZodTypeInternals<T["_zod"]["output"] | null, T["_zod"]["input"] | null> {
+  extends $ZodTypeInternals<core.output<T> | null, core.input<T> | null> {
   def: $ZodNullableDef<T>;
-  qin: T["_zod"]["qin"];
-  qout: T["_zod"]["qout"];
+  optionality: T["_zod"]["optionality"];
   isst: never;
   values: T["_zod"]["values"];
   pattern: RegExp;
@@ -3041,8 +2896,9 @@ export const $ZodNullable: core.$constructor<$ZodNullable> = /*@__PURE__*/ core.
   "$ZodNullable",
   (inst, def) => {
     $ZodType.init(inst, def);
-    inst._zod.qin = def.innerType._zod.qin;
-    inst._zod.qout = def.innerType._zod.qout;
+    inst._zod.optionality = def.innerType._zod.optionality;
+    // inst._zod.qin = def.innerType._zod.qin;
+    // inst._zod.qout = def.innerType._zod.qout;
 
     const pattern = (def.innerType as any)._zod.pattern;
     if (pattern) inst._zod.pattern = new RegExp(`^(${util.cleanRegex(pattern.source)}|null)$`);
@@ -3067,17 +2923,18 @@ export const $ZodNullable: core.$constructor<$ZodNullable> = /*@__PURE__*/ core.
 export interface $ZodDefaultDef<T extends $ZodType = $ZodType> extends $ZodTypeDef {
   type: "default";
   innerType: T;
-  defaultValue: () => util.NoUndefined<T["_zod"]["output"]>;
+  defaultValue: () => util.NoUndefined<core.output<T>>;
 }
 
 export interface $ZodDefaultInternals<T extends $ZodType = $ZodType>
   extends $ZodTypeInternals<
     // this is pragmatic but not strictly correct
-    util.NoUndefined<T["_zod"]["output"]>,
-    T["_zod"]["input"] | undefined
+    util.NoUndefined<core.output<T>>,
+    core.input<T> | undefined
   > {
   def: $ZodDefaultDef<T>;
-  qin: "true";
+  // qin: "true";
+  optionality: "defaulted";
   isst: never;
   values: T["_zod"]["values"];
 }
@@ -3091,6 +2948,8 @@ export const $ZodDefault: core.$constructor<$ZodDefault> = /*@__PURE__*/ core.$c
   (inst, def) => {
     $ZodType.init(inst, def);
 
+    // inst._zod.qin = "true";
+    inst._zod.optionality = "defaulted";
     inst._zod.values = def.innerType._zod.values;
 
     inst._zod.parse = (payload, ctx) => {
@@ -3129,7 +2988,7 @@ export interface $ZodNonOptionalDef<T extends $ZodType = $ZodType> extends $ZodT
 }
 
 export interface $ZodNonOptionalInternals<T extends $ZodType = $ZodType>
-  extends $ZodTypeInternals<util.NoUndefined<T["_zod"]["output"]>, util.NoUndefined<T["_zod"]["input"]>> {
+  extends $ZodTypeInternals<util.NoUndefined<core.output<T>>, util.NoUndefined<core.input<T>>> {
   def: $ZodNonOptionalDef<T>;
   isst: errors.$ZodIssueInvalidType;
   values: T["_zod"]["values"];
@@ -3219,8 +3078,7 @@ export interface $ZodSuccessDef extends $ZodTypeDef {
   innerType: $ZodType;
 }
 
-export interface $ZodSuccessInternals<T extends $ZodType = $ZodType>
-  extends $ZodTypeInternals<boolean, T["_zod"]["input"]> {
+export interface $ZodSuccessInternals<T extends $ZodType = $ZodType> extends $ZodTypeInternals<boolean, core.input<T>> {
   def: $ZodSuccessDef;
   isst: never;
 }
@@ -3268,10 +3126,12 @@ export interface $ZodCatchDef extends $ZodTypeDef {
 }
 
 export interface $ZodCatchInternals<T extends $ZodType = $ZodType>
-  extends $ZodTypeInternals<T["_zod"]["output"], util.Loose<T["_zod"]["input"]>> {
+  extends $ZodTypeInternals<core.output<T>, util.Loose<core.input<T>>> {
   def: $ZodCatchDef;
-  qin: T["_zod"]["qin"];
-  qout: T["_zod"]["qout"];
+  // qin: T["_zod"]["qin"];
+  // qout: T["_zod"]["qout"];
+
+  optionality: T["_zod"]["optionality"];
   isst: never;
   values: T["_zod"]["values"];
 }
@@ -3283,7 +3143,8 @@ export interface $ZodCatch<T extends $ZodType = $ZodType> extends $ZodType {
 export const $ZodCatch: core.$constructor<$ZodCatch> = /*@__PURE__*/ core.$constructor("$ZodCatch", (inst, def) => {
   $ZodType.init(inst, def);
   // inst._zod.qin = def.innerType._zod.qin;
-  inst._zod.qout = def.innerType._zod.qout;
+  // inst._zod.qout = def.innerType._zod.qout;
+  inst._zod.optionality = def.innerType._zod.optionality;
   inst._zod.values = def.innerType._zod.values;
 
   inst._zod.parse = (payload, ctx) => {
@@ -3369,7 +3230,7 @@ export interface $ZodPipeDef<A extends $ZodType = $ZodType, B extends $ZodType =
 }
 
 export interface $ZodPipeInternals<A extends $ZodType = $ZodType, B extends $ZodType = $ZodType>
-  extends $ZodTypeInternals<B["_zod"]["output"], A["_zod"]["input"]> {
+  extends $ZodTypeInternals<core.output<B>, core.input<A>> {
   def: $ZodPipeDef<A, B>;
   isst: never;
   values: A["_zod"]["values"];
@@ -3416,10 +3277,11 @@ export interface $ZodReadonlyDef extends $ZodTypeDef {
 }
 
 export interface $ZodReadonlyInternals<T extends $ZodType = $ZodType>
-  extends $ZodTypeInternals<util.MakeReadonly<T["_zod"]["output"]>, util.MakeReadonly<T["_zod"]["input"]>> {
+  extends $ZodTypeInternals<util.MakeReadonly<core.output<T>>, util.MakeReadonly<core.input<T>>> {
   def: $ZodReadonlyDef;
-  qin: T["_zod"]["qin"];
-  qout: T["_zod"]["qout"];
+  // qin: T["_zod"]["qin"];
+  // qout: T["_zod"]["qout"];
+  optionality: T["_zod"]["optionality"];
   isst: never;
   disc: T["_zod"]["disc"];
 }
@@ -3434,7 +3296,8 @@ export const $ZodReadonly: core.$constructor<$ZodReadonly> = /*@__PURE__*/ core.
     $ZodType.init(inst, def);
     util.defineLazy(inst._zod, "disc", () => def.innerType._zod.disc);
     // inst._zod.qin = def.innerType._zod.qin;
-    inst._zod.qout = def.innerType._zod.qout;
+    // inst._zod.qout = def.innerType._zod.qout;
+    inst._zod.optionality = def.innerType._zod.optionality;
 
     inst._zod.parse = (payload, ctx) => {
       const result = def.innerType._zod.run(payload, ctx);
@@ -3489,9 +3352,7 @@ type AppendToTemplateLiteral<
   Suffix extends $LiteralPart | $ZodType,
 > = Suffix extends $LiteralPart
   ? `${Template}${UndefinedToEmptyString<Suffix>}`
-  : Suffix extends $ZodType
-    ? `${Template}${UndefinedToEmptyString<$LiteralPart & Suffix["_zod"]["output"]>}`
-    : never;
+  : `${Template}${UndefinedToEmptyString<$LiteralPart & core.output<Suffix & $ZodType>>}`;
 
 export type $PartsToTemplateLiteral<Parts extends $TemplateLiteralPart[]> = [] extends Parts
   ? ``
@@ -3568,7 +3429,7 @@ export interface $ZodPromiseDef extends $ZodTypeDef {
 }
 
 export interface $ZodPromiseInternals<T extends $ZodType = $ZodType>
-  extends $ZodTypeInternals<T["_zod"]["output"], util.MaybeAsync<T["_zod"]["input"]>> {
+  extends $ZodTypeInternals<core.output<T>, util.MaybeAsync<core.input<T>>> {
   def: $ZodPromiseDef;
   isst: never;
 }
@@ -3602,14 +3463,15 @@ export interface $ZodLazyDef extends $ZodTypeDef {
 }
 
 export interface $ZodLazyInternals<T extends $ZodType = $ZodType>
-  extends $ZodTypeInternals<T["_zod"]["output"], T["_zod"]["input"]> {
+  extends $ZodTypeInternals<core.output<T>, core.input<T>> {
   def: $ZodLazyDef;
   isst: never;
   _getter: T;
   pattern: T["_zod"]["pattern"];
   disc: T["_zod"]["disc"];
-  qin: T["_zod"]["qin"];
-  qout: T["_zod"]["qout"];
+  // qin: T["_zod"]["qin"];
+  // qout: T["_zod"]["qout"];
+  optionality: T["_zod"]["optionality"];
 }
 
 export interface $ZodLazy<T extends $ZodType = $ZodType> extends $ZodType {
@@ -3622,12 +3484,10 @@ export const $ZodLazy: core.$constructor<$ZodLazy> = /*@__PURE__*/ core.$constru
   util.defineLazy(inst._zod, "_getter", def.getter);
   util.defineLazy(inst._zod, "pattern", () => inst._zod._getter._zod.pattern);
   util.defineLazy(inst._zod, "disc", () => inst._zod._getter._zod.disc);
+  util.defineLazy(inst._zod, "optionality", () => inst._zod._getter._zod.optionality);
   inst._zod.parse = (payload, ctx) => {
     return inst._zod._getter._zod.run(payload, ctx);
   };
-  // qin and qout
-  util.defineLazy(inst._zod, "qin", () => inst._zod._getter._zod.qin);
-  util.defineLazy(inst._zod, "qout", () => inst._zod._getter._zod.qout);
 });
 
 ////////////////////////////////////////
@@ -3708,7 +3568,7 @@ export type $ZodTypes =
   | $ZodVoid
   | $ZodArray
   | $ZodObject
-  | $ZodInterface
+  // | $ZodInterface
   | $ZodUnion
   | $ZodIntersection
   | $ZodTuple
diff --git a/packages/core/src/to-json-schema.ts b/packages/core/src/to-json-schema.ts
index 1dc89662..39e5b1e2 100644
--- a/packages/core/src/to-json-schema.ts
+++ b/packages/core/src/to-json-schema.ts
@@ -271,8 +271,7 @@ export class JSONSchemaGenerator {
           json.items = this.process(def.element, { ...params, path: [...params.path, "items"] });
           break;
         }
-        case "object":
-        case "interface": {
+        case "object": {
           const json: JSONSchema.ObjectSchema = _json as any;
           json.type = "object";
           json.properties = {};
@@ -290,8 +289,17 @@ export class JSONSchemaGenerator {
 
           // required keys
           const allKeys = new Set(Object.keys(shape));
-          const optionalKeys = new Set(def.optional);
-          const requiredKeys = new Set([...allKeys].filter((key) => !optionalKeys.has(key)));
+          // const optionalKeys = new Set(def.optional);
+          const requiredKeys = new Set(
+            [...allKeys].filter((key) => {
+              const opt = def.shape[key]._zod.optionality;
+              if (this.io === "input") {
+                return opt === undefined;
+              } else {
+                return opt === undefined || opt === "defaulted";
+              }
+            })
+          );
           json.required = Array.from(requiredKeys);
 
           // catchall
@@ -482,7 +490,6 @@ export class JSONSchemaGenerator {
         case "pipe": {
           const innerType = this.io === "input" ? def.in : def.out;
           const inner = this.process(innerType, params);
-          // result.schema = inner;
           _json._ref = inner;
 
           break;
@@ -673,8 +680,8 @@ export class JSONSchemaGenerator {
 
     for (const entry of this.seen.entries()) {
       const seen = entry[1];
-      flattenRef(seen.schema);
-      if (seen.def) flattenRef(seen.def);
+      flattenRef(seen.schema, { target: this.target });
+      if (seen.def) flattenRef(seen.def, { target: this.target });
     }
 
     const result = { ...root.def };
@@ -707,12 +714,19 @@ export class JSONSchemaGenerator {
 }
 
 // flatten _refs
-const flattenRef = (schema: JSONSchema.BaseSchema) => {
+const flattenRef = (schema: JSONSchema.BaseSchema, params: Pick<ToJSONSchemaParams, "target">) => {
   const _schema = { ...schema };
-  if (schema._ref) flattenRef(schema._ref);
+  if (schema._ref) flattenRef(schema._ref, params);
   const ref = schema._ref;
-  Object.assign(schema, ref);
-  Object.assign(schema, _schema); // this is to prevent mutation of the original schema
+  if (ref) {
+    if (ref.$ref && params.target === "draft-7") {
+      schema.allOf = schema.allOf ?? [];
+      schema.allOf.push(ref);
+    } else {
+      Object.assign(schema, ref);
+      Object.assign(schema, _schema); // this is to prevent overwriting any fields in the original schema
+    }
+  }
   delete schema._ref;
 };
 
diff --git a/packages/core/src/util.ts b/packages/core/src/util.ts
index d40dd9af..b3f189b7 100644
--- a/packages/core/src/util.ts
+++ b/packages/core/src/util.ts
@@ -89,7 +89,7 @@ export type Exactly<T, X> = T & Record<Exclude<keyof X, keyof T>, never>;
 export type NoUndefined<T> = T extends undefined ? never : T;
 export type Loose<T> = T | {} | undefined | null;
 export type Mask<Keys extends PropertyKey> = { [K in string & Keys]?: true };
-export type Writeable<T> = { -readonly [P in keyof T]: T[P] };
+export type Writeable<T> = { -readonly [P in keyof T]: T[P] } & {};
 export type InexactPartial<T> = {
   [P in keyof T]?: T[P] | undefined;
 };
@@ -117,7 +117,9 @@ export type SomeObject = Record<PropertyKey, any>;
 export type Identity<T> = T;
 export type Flatten<T> = Identity<{ [k in keyof T]: T[k] }>;
 export type Mapped<T> = { [k in keyof T]: T[k] };
-
+export type Prettify<T> = {
+  [K in keyof T]: T[K];
+} & {};
 export type NoNeverKeys<T> = {
   [k in keyof T]: [T[k]] extends [never] ? never : k;
 }[keyof T];
@@ -541,92 +543,143 @@ export function stringifyPrimitive(value: any): string {
   return `${value}`;
 }
 
+// export function objectShapeMeta(rawShape: schemas.$ZodShape): schemas.$ZodShape {
+//   const shape: Writeable<schemas.$ZodShape> = {};
+//   for (const key in rawShape) {
+//     shape[key] = {
+//       type: rawShape[key],
+//       optionality: rawShape[key]._zod.optionality,
+//     };
+//     // if (rawShape[key]._zod.qin) {
+//     //   shape[key].optionality = "defaulted";
+//     // } else if (rawShape[key]._zod.qout) {
+//     //   shape[key].optionality = "optional";
+//     // } else {
+//     //   shape[key].optionality = "required";
+//     // }
+//   }
+//   return shape;
+// }
+// export function interfaceShapeMeta(shape: schemas.$ZodShape): schemas.$ZodShape {
+//   const shapeMeta: Writeable<schemas.$ZodShape> = {};
+//   for (const key in shape) {
+//     if(key[0] === "?") {
+//     shapeMeta[key] ??= { optionality: "required" }; // default
+//     if (shape[key]._zod.qin) {
+//       shapeMeta[key].optionality = "defaulted";
+//     } else if (shape[key]._zod.qout) {
+//       shapeMeta[key].optionality = "optional";
+//     }
+//   }
+//   return shapeMeta;
+// }
 export function optionalObjectKeys(shape: schemas.$ZodShape): string[] {
   return Object.keys(shape).filter((k) => {
-    return shape[k]._zod.qout === "true";
+    return shape[k]._zod.optionality === "optional";
   });
 }
 
-export function optionalInterfaceKeys(shape: schemas.$ZodLooseShape): string[] {
-  return Object.keys(shape)
-    .filter((k) => {
-      return k.endsWith("?");
-    })
-    .map((k) => k.replace(/\?$/, ""));
-}
-
-export type CleanInterfaceShape<T extends object> = Identity<{
-  [k in keyof T as k extends `${infer K}?` ? K : k extends `?${infer K}` ? K : k]: T[k];
-}>;
-export type CleanKeys<T extends PropertyKey> = T extends `${infer K}?` ? K : T extends `?${infer K}` ? K : T;
-export type OptionalInterfaceKeys<T extends PropertyKey> = T extends `${infer K}?` ? K : never;
-export type DefaultedInterfaceKeys<T extends PropertyKey> = T extends `?${infer K}` ? K : never;
-
-export type InitInterfaceParams<T extends schemas.$ZodLooseShape, Extra extends Record<string, unknown>> = Identity<{
-  optional: OptionalInterfaceKeys<keyof T>;
-  defaulted: DefaultedInterfaceKeys<keyof T>;
-  extra: Extra;
-}>;
-
-export type MergeOptional<A extends schemas.$ZodInterface, B extends schemas.$ZodInterface> =
-  | Exclude<A["_zod"]["optional"], keyof B["_zod"]["def"]["shape"]>
-  | B["_zod"]["optional"];
-export type MergeDefaulted<A extends schemas.$ZodInterface, B extends schemas.$ZodInterface> =
-  | Exclude<A["_zod"]["defaulted"], keyof B["_zod"]["def"]["shape"]>
-  | B["_zod"]["defaulted"];
-
-export type MergeInterfaceParams<
-  A extends schemas.$ZodInterface,
-  B extends schemas.$ZodInterface,
-  // BKeys extends PropertyKey,
-> = Identity<{
-  optional: Exclude<A["_zod"]["optional"], keyof B["_zod"]["def"]["shape"]> | B["_zod"]["optional"];
-  defaulted: Exclude<A["_zod"]["defaulted"], keyof B["_zod"]["def"]["shape"]> | B["_zod"]["defaulted"];
-  extra: A["_zod"]["extra"];
-}>;
-
-export type ExtendInterfaceParams<A extends schemas.$ZodInterface, Shape extends schemas.$ZodLooseShape> = Identity<{
-  optional: Exclude<A["_zod"]["optional"], CleanKeys<keyof Shape>> | OptionalInterfaceKeys<keyof Shape>;
-  defaulted: Exclude<A["_zod"]["defaulted"], CleanKeys<keyof Shape>> | DefaultedInterfaceKeys<keyof Shape>;
-  extra: A["_zod"]["extra"];
-}>;
-export type ExtendInterfaceShape<A extends schemas.$ZodLooseShape, B extends schemas.$ZodLooseShape> = Extend<
-  A,
-  CleanInterfaceShape<B>
->;
-export type InterfaceParams<T extends schemas.$ZodInterface> = {
-  optional: T["_zod"]["optional"];
-  defaulted: T["_zod"]["defaulted"];
-  extra: T["_zod"]["extra"];
+// export function optionalInterfaceKeys(shape: schemas.$ZodLooseShape): string[] {
+//   return Object.keys(shape)
+//     .filter((k) => {
+//       return k.endsWith("?");
+//     })
+//     .map((k) => k.replace(/\?$/, ""));
+// }
+
+// type CleanInterfaceShape<T extends object> = Identity<{
+//   [k in keyof T as k extends `${infer K}?` ? K : k extends `?${infer K}` ? K : k]: T[k];
+// }>;
+export type CleanKey<T extends PropertyKey> = T extends `?${infer K}` ? K : T extends `${infer K}?` ? K : T;
+export type ToCleanMap<T extends schemas.$ZodLooseShape> = {
+  [k in keyof T]: k extends `?${infer K}` ? K : k extends `${infer K}?` ? K : k;
 };
-
-export function cleanInterfaceKey(key: string): string {
-  return key.replace(/^\?/, "").replace(/\?$/, "");
-}
-
-export function cleanInterfaceShape<T extends schemas.$ZodLooseShape>(
-  _shape: T
-): {
-  shape: CleanInterfaceShape<T>;
-  keyMap: Record<string, string>;
-  optional: string[];
-  defaulted: string[];
-} {
-  const keyMap: Record<string, string> = {};
-  const shape = {} as CleanInterfaceShape<T>;
-  const optional: string[] = [];
-  const defaulted: string[] = [];
-
-  for (const [key, value] of Object.entries(_shape)) {
-    if (key.endsWith("?")) optional.push(key.slice(0, -1));
-    if (key.startsWith("?")) defaulted.push(key.slice(1));
-    const cleanKey = cleanInterfaceKey(key);
-    (shape as any)[cleanKey] = value;
-    keyMap[cleanKey] = key;
-  }
-
-  return { shape, keyMap, optional, defaulted };
-}
+export type FromCleanMap<T extends schemas.$ZodLooseShape> = {
+  [k in keyof T as k extends `?${infer K}` ? K : k extends `${infer K}?` ? K : k]: k;
+};
+// export type OptionalInterfaceKeys<T extends PropertyKey> = T extends `${infer K}?` ? K : never;
+// export type DefaultedInterfaceKeys<T extends PropertyKey> = T extends `?${infer K}` ? K : never;
+// export type PickShape<T extends schemas.$ZodObject> = Flatten<
+//   Pick<T['_zod'], keyof Shape & this["_cleanToRaw"][string & keyof M]>
+// >;
+// export type InitInterfaceParams<T extends schemas.$ZodLooseShape, Extra extends Record<string, unknown>> = Identity<{
+//   optional: OptionalInterfaceKeys<keyof T>;
+//   defaulted: DefaultedInterfaceKeys<keyof T>;
+//   extra: Extra;
+// }>;
+
+// export type MergeOptional<A extends schemas.$ZodInterface, B extends schemas.$ZodInterface> =
+//   | Exclude<A["_zod"]["optional"], keyof B["_zod"]["def"]["shape"]>
+//   | B["_zod"]["optional"];
+// export type MergeDefaulted<A extends schemas.$ZodInterface, B extends schemas.$ZodInterface> =
+//   | Exclude<A["_zod"]["defaulted"], keyof B["_zod"]["def"]["shape"]>
+//   | B["_zod"]["defaulted"];
+
+// export type MergeInterfaceParams<
+//   A extends schemas.$ZodInterface,
+//   B extends schemas.$ZodInterface,
+//   // BKeys extends PropertyKey,
+// > = Identity<{
+//   optional: Exclude<A["_zod"]["optional"], keyof B["_zod"]["def"]["shape"]> | B["_zod"]["optional"];
+//   defaulted: Exclude<A["_zod"]["defaulted"], keyof B["_zod"]["def"]["shape"]> | B["_zod"]["defaulted"];
+//   extra: A["_zod"]["extra"];
+// }>;
+
+// export type ExtendInterfaceParams<A extends schemas.$ZodInterface, Shape extends schemas.$ZodLooseShape> = Identity<{
+//   optional: Exclude<A["_zod"]["optional"], CleanKey<keyof Shape>> | OptionalInterfaceKeys<keyof Shape>;
+//   defaulted: Exclude<A["_zod"]["defaulted"], CleanKey<keyof Shape>> | DefaultedInterfaceKeys<keyof Shape>;
+//   extra: A["_zod"]["extra"];
+// }>;
+
+// export type ExtendInterfaceShape<A extends schemas.$ZodLooseShape, B extends schemas.$ZodLooseShape> = Extend<A, B>;
+// export type InterfaceParams<T extends schemas.$ZodInterface> = {
+//   optional: T["_zod"]["optional"];
+//   defaulted: T["_zod"]["defaulted"];
+//   extra: T["_zod"]["extra"];
+// };
+
+// export function cleanInterfaceKey(key: string): string {
+//   if (key.startsWith("?")) return key.slice(1);
+//   if (key.endsWith("?")) return key.slice(0, -1);
+//   return key;
+//   // return key.replace(/^\?/, "").replace(/\?$/, "");
+// }
+
+// export function cleanInterfaceShape<T extends schemas.$ZodLooseShape>(
+//   _shape: T
+// ): {
+//   // shape: CleanInterfaceShape<T>;
+//   keyMap: Record<string, string>;
+//   shape: schemas.$ZodShape;
+// } {
+//   console.log({ _shape });
+//   const keyMap: Record<string, string> = {};
+//   const shape: Writeable<schemas.$ZodShape> = {};
+
+//   for (const [key, type] of Object.entries(_shape as schemas.$ZodShape)) {
+//     if (!type._zod) {
+//       throw new Error(`Invalid value in shape at "${key}": not a Zod schema`);
+//     }
+//     console.log("key", key);
+//     const cleanKey = key.endsWith("?") ? key.slice(0, -1) : key;
+
+//     shape[cleanKey] = { type, optionality: type._zod.optionality };
+
+//     // question mark overrides entry optionality
+//     if (key.endsWith("?")) {
+//       shape[cleanKey].optionality = "optional";
+//     }
+
+//     // default overrides question mark
+//     if (type._zod.optionality === "defaulted") {
+//       shape[cleanKey].optionality = "defaulted";
+//     }
+
+//     keyMap[cleanKey] = key;
+//   }
+
+//   return { shape, keyMap };
+// }
 
 export const NUMBER_FORMAT_RANGES: Record<checks.$ZodNumberFormats, [number, number]> = {
   safeint: [Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER],
@@ -641,89 +694,85 @@ export const BIGINT_FORMAT_RANGES: Record<checks.$ZodBigIntFormats, [bigint, big
   uint64: [/* @__PURE__*/ BigInt(0), /* @__PURE__*/ BigInt("18446744073709551615")],
 };
 
-export function pick(schema: schemas.$ZodObjectLike, mask: object): any {
+export function pick(schema: schemas.$ZodObject, mask: Record<string, unknown>): any {
+  // const newShape: Writeable<schemas.$ZodShape> = {};
   const newShape: Writeable<schemas.$ZodShape> = {};
-  const newOptional: string[] = [];
-  const currShape = schema._zod.def.shape;
-  const currOptional = new Set(schema._zod.def.optional);
-  // const currDefaulted = new Set(schema._zod.def.defaulted);
+  // const newOptional: string[] = [];
+  const currDef = schema._zod.def; //.shape;
 
   for (const key in mask) {
-    if (!(key in currShape)) {
+    if (!(key in currDef.shape)) {
       throw new Error(`Unrecognized key: "${key}"`);
     }
-    if (!(mask as any)[key]) continue;
+    if (!mask[key]) continue;
 
     // pick key
-    newShape[key] = currShape[key];
-    if (currOptional.has(key)) {
-      newOptional.push(key);
-    }
+    newShape[key] = currDef.shape[key];
   }
 
   return clone(schema, {
     ...schema._zod.def,
     shape: newShape,
-    optional: newOptional,
     checks: [],
   }) as any;
 }
 
-export function omit(schema: schemas.$ZodObjectLike, mask: object): any {
+export function omit(schema: schemas.$ZodObject, mask: object): any {
+  // const newShape: Writeable<schemas.$ZodShape> = { ...schema._zod.def.shape };
   const newShape: Writeable<schemas.$ZodShape> = { ...schema._zod.def.shape };
-  const newOptional = new Set(schema._zod.def.optional);
+  const currDef = schema._zod.def; //.shape;
+  // const newOptional = new Set(schema._zod.def.optional);
   for (const key in mask) {
-    if (!(key in schema._zod.def.shape)) {
+    if (!(key in currDef.shape)) {
       throw new Error(`Unrecognized key: "${key}"`);
     }
     if (!(mask as any)[key]) continue;
 
     delete newShape[key];
-    newOptional.delete(key);
   }
   return clone(schema, {
     ...schema._zod.def,
     shape: newShape,
-    optional: [...newOptional],
     checks: [],
   });
 }
 
-export function extend(schema: schemas.$ZodObjectLike, shape: schemas.$ZodShape): any {
+export function extend(schema: schemas.$ZodObject, shape: schemas.$ZodShape): any {
   const def = {
     ...schema._zod.def,
     get shape() {
       const _shape = { ...schema._zod.def.shape, ...shape };
-      assignProp(this, "shape", _shape);
+      assignProp(this, "shape", _shape); // self-caching
       return _shape;
     },
     checks: [], // delete existing checks
   } as any;
-  defineLazy(def, "shape", () => ({ ...schema._zod.def.shape, ...shape }));
   return clone(schema, def) as any;
 }
 
-export function mergeObjectLike(a: schemas.$ZodObjectLike, b: schemas.$ZodObjectLike): any {
-  const bKeys = new Set(Object.keys(b._zod.def.shape));
-  const optional = [...a._zod.def.optional.filter((k) => !bKeys.has(k)), ...b._zod.def.optional];
+export function mergeObjectLike(a: schemas.$ZodObject, b: schemas.$ZodObject): any {
+  // const shapeMeta = { ...a._zod.def.shapeMeta, ...b._zod.def.shapeMeta };
+  // const bKeys = new Set(Object.keys(b._zod.def.shape));
+  // const optional = [...a._zod.def.optional.filter((k) => !bKeys.has(k)), ...b._zod.def.optional];
 
   return clone(a, {
     ...a._zod.def,
     get shape() {
       const _shape = { ...a._zod.def.shape, ...b._zod.def.shape };
-      assignProp(this, "shape", _shape);
+      assignProp(this, "shape", _shape); // self-caching
       return _shape;
       // return { ...a._zod.def.shape, ...b._zod.def.shape };
     },
-    optional,
+    // shapeMeta: { ...a._zod.def.shapeMeta, ...b._zod.def.shapeMeta },
     catchall: b._zod.def.catchall,
     checks: [], // delete existing checks
   }) as any;
 }
 
-export function extendObjectLike(a: schemas.$ZodObjectLike, b: schemas.$ZodObjectLike): any {
-  const bKeys = new Set(Object.keys(b._zod.def.shape));
-  const optional = [...a._zod.def.optional.filter((k) => !bKeys.has(k)), ...b._zod.def.optional];
+export function extendObjectLike(a: schemas.$ZodObject, b: schemas.$ZodObject): any {
+  // const bKeys = new Set(Object.keys(b._zod.def.shape));
+  // const optional = [...a._zod.def.optional.filter((k) => !bKeys.has(k)), ...b._zod.def.optional];
+
   return clone(a, {
     ...a._zod.def,
     get shape() {
@@ -732,55 +781,67 @@ export function extendObjectLike(a: schemas.$ZodObjectLike, b: schemas.$ZodObjec
       return _shape;
       // return { ...a._zod.def.shape, ...b._zod.def.shape };
     },
-    optional,
+    // shapeMeta: { ...a._zod.def.shapeMeta, ...b._zod.def.shapeMeta },
+    // optional,
     checks: [], // delete existent checks
   }) as any;
 }
 
 export function partialObjectLike(
-  Class: SchemaClass<schemas.$ZodOptional>,
-  schema: schemas.$ZodObjectLike,
+  Class: SchemaClass<schemas.$ZodOptional> | null,
+  schema: schemas.$ZodObject,
   mask: object | undefined
 ): any {
-  const shape: Writeable<schemas.$ZodShape> = { ...schema._zod.def.shape };
-  const optional: Set<string> = new Set(schema._zod.def.optional);
+  console.log("PartialObjectLike");
+  // const shape: Writeable<schemas.$ZodShape> = { ...schema._zod.def.shape };
+  const oldShape = schema._zod.def.shape;
+  const shape: Writeable<schemas.$ZodShape> = { ...oldShape };
+  // const optional: Set<string> = new Set(schema._zod.def.optional);
 
   if (mask) {
     for (const key in mask) {
-      if (!(key in shape)) {
+      if (!(key in oldShape)) {
         throw new Error(`Unrecognized key: "${key}"`);
       }
       if (!(mask as any)[key]) continue;
-      shape[key] = new Class({
-        type: "optional",
-        innerType: schema._zod.def.shape[key],
-      });
-      optional.add(key);
+      shape[key] = Class
+        ? new Class({
+            type: "optional",
+            innerType: oldShape[key],
+          })
+        : oldShape[key];
+      // optional.add(key);
+      // shapeMeta[key] = { ...shapeMeta[key], optionality: "optional" };
     }
   } else {
-    for (const key in schema._zod.def.shape) {
-      shape[key] = new Class({
-        type: "optional",
-        innerType: schema._zod.def.shape[key],
-      });
-      optional.add(key);
+    for (const key in oldShape) {
+      shape[key] = Class
+        ? new Class({
+            type: "optional",
+            innerType: oldShape[key],
+          })
+        : oldShape[key];
+      // shapeMeta[key] = { ...shapeMeta[key], optionality: "optional" };
+      // optional.add(key);
     }
   }
 
   return clone(schema, {
     ...schema._zod.def,
     shape,
-    optional: [...optional],
+    // shapeMeta,
+    // optional: [...optional],
     checks: [],
   }) as any;
 }
 
 export function requiredObjectLike(
   Class: SchemaClass<schemas.$ZodNonOptional>,
-  schema: schemas.$ZodObjectLike,
+  schema: schemas.$ZodObject,
   mask: object | undefined
 ): any {
-  const shape: Writeable<schemas.$ZodShape> = { ...schema._zod.def.shape };
+  const oldShape = schema._zod.def.shape;
+  const shape: Writeable<schemas.$ZodShape> = { ...oldShape };
 
   if (mask) {
     for (const key in mask) {
@@ -791,15 +852,15 @@ export function requiredObjectLike(
       // overwrite with non-optional
       shape[key] = new Class({
         type: "nonoptional",
-        innerType: schema._zod.def.shape[key],
+        innerType: oldShape[key],
       });
     }
   } else {
-    for (const key in schema._zod.def.shape) {
+    for (const key in oldShape) {
       // overwrite with non-optional
       shape[key] = new Class({
         type: "nonoptional",
-        innerType: schema._zod.def.shape[key],
+        innerType: oldShape[key],
       });
     }
   }
@@ -807,63 +868,21 @@ export function requiredObjectLike(
   return clone(schema, {
     ...schema._zod.def,
     shape,
-    optional: [],
+    // optional: [],
     checks: [],
   }) as any;
 }
 
-// add question mark to all non-optional keys
-export type PartialInterfaceShape<T extends schemas.$ZodShape, Keys extends string> = Flatten<
-  Omit<T, Keys> & {
-    [k in Keys as k extends `${string}?` ? k : `${string & k}?`]: T[k];
-  }
->;
-
-export type InterfaceKeys<Keys extends string> = string extends Keys
-  ? string
-  : Keys extends `${infer K}?`
-    ? K
-    : Keys extends `?${infer K}`
-      ? K
-      : Keys;
+// export type InterfaceKeys<Keys extends string> = string extends Keys
+//   ? string
+//   : Keys extends `${infer K}?`
+//     ? K
+//     : Keys extends `?${infer K}`
+//       ? K
+//       : Keys;
 
 export type Constructor<T, Def extends any[] = any[]> = new (...args: Def) => T;
 
-export function normalizeObjectLikeDef(def: schemas.$ZodObjectLikeDef): {
-  shape: Readonly<Record<string, schemas.$ZodType<unknown, unknown>>>;
-  // keyMap: Record<string, string>;
-  keys: string[];
-  keySet: Set<string>;
-  numKeys: number;
-  optionalKeys: Set<string>;
-} {
-  if (def.type === "interface") {
-    const keys = Object.keys(def.shape);
-    const keySet = new Set(Object.keys(def.shape));
-
-    return {
-      shape: { ...def.shape }, // resolve getters
-      keys,
-      keySet,
-      numKeys: keys.length,
-      optionalKeys: new Set(def.optional),
-    };
-  }
-  if (def.type === "object") {
-    const keys = Object.keys(def.shape);
-    const keySet: Set<string> = new Set(Object.keys(def.shape));
-
-    return {
-      shape: { ...def.shape }, // resolve getters
-      keys,
-      keySet,
-      numKeys: keys.length,
-      optionalKeys: new Set(def.optional),
-    };
-  }
-  throw new Error("Invalid object-like type");
-}
-
 export function aborted(x: schemas.ParsePayload, startIndex = 0): boolean {
   for (let i = startIndex; i < x.issues.length; i++) {
     if (x.issues[i].continue !== true) return true;
diff --git a/packages/mini/src/schemas.ts b/packages/mini/src/schemas.ts
index 368967b6..4bacba77 100644
--- a/packages/mini/src/schemas.ts
+++ b/packages/mini/src/schemas.ts
@@ -7,7 +7,7 @@ export * as iso from "./iso.js";
 
 type SomeType = core.$ZodType;
 
-export interface ZodMiniType<out O = unknown, out I = unknown> extends core.$ZodType<O, I> {
+export interface ZodMiniType<out Output = unknown, out Input = unknown> extends core.$ZodType<Output, Input> {
   check(...checks: (core.CheckFn<this["_zod"]["output"]> | core.$ZodCheck<this["_zod"]["output"]>)[]): this;
   clone(def?: this["_zod"]["def"]): this;
   register<R extends core.$ZodRegistry>(
@@ -20,7 +20,7 @@ export interface ZodMiniType<out O = unknown, out I = unknown> extends core.$Zod
   ): this;
   brand<T extends PropertyKey = PropertyKey>(
     value?: T
-  ): this & Record<"_zod", Record<"output", this["_zod"]["output"] & core.$brand<T>>>;
+  ): PropertyKey extends T ? this : this & Record<"_zod", Record<"~output", core.output<this> & core.$brand<T>>>;
 
   def: this["_zod"]["def"];
 
@@ -684,125 +684,130 @@ export function array<T extends SomeType>(element: SomeType, params?: any): ZodM
 }
 
 // ZodMiniObjectLike
-export interface ZodMiniObjectLike<out O = object, out I = object> extends ZodMiniType {
-  _zod: core.$ZodObjectLikeInternals<O, I>;
-}
-export const ZodMiniObjectLike: core.$constructor<ZodMiniObjectLike> = /*@__PURE__*/ core.$constructor(
-  "ZodMiniObjectLike",
-  (inst, def) => {
-    core.$ZodObjectLike.init(inst, def);
-    ZodMiniType.init(inst, def);
-  }
-);
+// export interface ZodMiniObjectLike<out O = object, out I = object> extends ZodMiniType {
+//   _zod: core.$ZodObjectInternals<O ,I>;
+//   shape: core.$ZodShape;
+// }
+// export const ZodMiniObjectLike: core.$constructor<ZodMiniObjectLike> = /*@__PURE__*/ core.$constructor(
+//   "ZodMiniObjectLike",
+//   (inst, def) => {
+//     core.$ZodObject.init(inst, def);
+//     ZodMiniType.init(inst, def);
+//   }
+// );
 
 // .keyof
-export function keyof<T extends ZodMiniObject>(schema: T): ZodMiniLiteral<keyof T["_zod"]["def"]["shape"]>;
-export function keyof<T extends ZodMiniInterface>(schema: T): ZodMiniLiteral<keyof T["_zod"]["output"]>;
-export function keyof(schema: ZodMiniObjectLike) {
-  const shape =
-    schema._zod.def.type === "interface"
-      ? util.cleanInterfaceShape(schema._zod.def.shape).shape
-      : schema._zod.def.shape;
-
+export function keyof<T extends ZodMiniObject>(schema: T): ZodMiniLiteral<keyof T["shape"]> {
+  const shape = schema._zod.def.shape;
   return literal(Object.keys(shape)) as any;
 }
 
 // ZodMiniInterface
-export interface ZodMiniInterface<
-  Shape extends core.$ZodLooseShape = core.$ZodLooseShape,
-  Params extends core.$ZodInterfaceNamedParams = {
-    optional: string & keyof Shape;
-    defaulted: string & keyof Shape;
-    extra: {};
-  },
-> extends ZodMiniType {
-  _zod: core.$ZodInterfaceInternals<Shape, Params>;
-}
-export const ZodMiniInterface: core.$constructor<ZodMiniInterface> = /*@__PURE__*/ core.$constructor(
-  "ZodMiniInterface",
-  (inst, def) => {
-    core.$ZodInterface.init(inst, def);
-    ZodMiniType.init(inst, def);
-  }
-);
-
-function _interface<T extends core.$ZodLooseShape>(
-  shape: T,
-  params?: string | core.$ZodInterfaceParams,
-  Class: util.Constructor<ZodMiniInterface> = ZodMiniInterface
-): ZodMiniInterface<util.CleanInterfaceShape<T>, util.InitInterfaceParams<T, {}>> {
-  const cleaned = util.cached(() => util.cleanInterfaceShape(shape));
-  const def: core.$ZodInterfaceDef = {
-    type: "interface",
-    get shape() {
-      const _shape = cleaned.value.shape;
-      util.assignProp(this, "shape", _shape);
-      return _shape;
-      // return cleaned.value.shape;
-    },
-    get optional() {
-      return cleaned.value.optional;
-    },
-    ...util.normalizeParams(params),
-  };
-  return new Class(def) as any;
-}
-export { _interface as interface };
-
-// strictInterface
-
-export function strictInterface<T extends core.$ZodLooseShape>(
-  shape: T,
-  params?: string | core.$ZodInterfaceParams
-): ZodMiniInterface<util.CleanInterfaceShape<T>, util.InitInterfaceParams<T, {}>> {
-  const cleaned = util.cached(() => util.cleanInterfaceShape(shape));
-  const def: core.$ZodInterfaceDef = {
-    type: "interface",
-    get shape() {
-      const _shape = cleaned.value.shape;
-      util.assignProp(this, "shape", _shape);
-      return _shape;
-      // return cleaned.value.shape;
-    },
-    get optional() {
-      return cleaned.value.optional;
-    },
-    catchall: never(),
-    ...util.normalizeParams(params),
-  };
-  return new ZodMiniInterface(def) as any;
-}
-
-// looseInterface
+// export interface ZodMiniInterface<
+//   // @ts-ignore Cast variance
+//   out Shape extends core.$ZodLooseShape = core.$ZodLooseShape,
+//   out OutExtra extends Record<string, unknown> = Record<string, unknown>,
+//   out InExtra extends Record<string, unknown> = Record<string, unknown>,
+// > extends ZodMiniType {
+//   _zod: core.$ZodInterfaceInternals<Shape, OutExtra, InExtra>;
+//   shape: Shape;
+//   // _rawToClean: util.ToCleanMap<Shape>;
+//   // _cleanToRaw: util.FromCleanMap<Shape>;
+// }
+// export const ZodMiniInterface: core.$constructor<ZodMiniInterface> = /*@__PURE__*/ core.$constructor(
+//   "ZodMiniInterface",
+//   (inst, def) => {
+//     core.$ZodInterface.init(inst, def);
+//     ZodMiniType.init(inst, def);
+//   }
+// );
+
+// export type ProcessInterfaceShape<T extends core.$ZodLooseShape> = {
+//   [k in keyof T as k extends `${infer K}?` ? K : never]?: T[k];
+// } & {
+//   [k in keyof T as k extends `${string}?` ? never : k]: T[k];
+// };
+
+// function _interface<T extends core.$ZodLooseShape>(
+//   shape: T,
+//   params?: string | core.$ZodInterfaceParams,
+//   Class: util.Constructor<ZodMiniInterface> = ZodMiniInterface
+// ): ZodMiniInterface<T, {}, {}> {
+//   const cleaned = util.cached(() => util.cleanInterfaceShape(shape));
+//   const def: core.$ZodInterfaceDef = {
+//     type: "interface",
+//     get shape() {
+//       const _shape = cleaned.value.shape;
+//       util.assignProp(this, "shape", _shape);
+//       return _shape;
+//       // return cleaned.value.shape;
+//     },
+//     // get shapeMeta() {
+//     //   return cleaned.value.shapeMeta;
+//     // },
+//     ...util.normalizeParams(params),
+//   };
+//   return new Class(def) as any;
+// }
+// export { _interface as interface };
+
+// // strictInterface
+
+// export function strictInterface<T extends core.$ZodLooseShape>(
+//   shape: T,
+//   params?: string | core.$ZodInterfaceParams
+// ): ZodMiniInterface<ProcessInterfaceShape<T>, {}, {}> {
+//   const cleaned = util.cached(() => util.cleanInterfaceShape(shape));
+//   const def: core.$ZodInterfaceDef = {
+//     type: "interface",
+//     get shape() {
+//       const _shape = cleaned.value.shape;
+//       util.assignProp(this, "shape", _shape);
+//       return _shape;
+//       // return cleaned.value.shape;
+//     },
+//     // get shapeMeta() {
+//     //   return cleaned.value.shapeMeta;
+//     // },
+//     catchall: never(),
+//     ...util.normalizeParams(params),
+//   };
+//   return new ZodMiniInterface(def) as any;
+// }
 
-export function looseInterface<T extends core.$ZodLooseShape>(
-  shape: T,
-  params?: string | core.$ZodInterfaceParams
-): ZodMiniInterface<util.CleanInterfaceShape<T>, util.InitInterfaceParams<T, Record<string, unknown>>> {
-  const cleaned = util.cached(() => util.cleanInterfaceShape(shape));
-  const def: core.$ZodInterfaceDef = {
-    type: "interface",
-    get optional() {
-      return cleaned.value.optional;
-    },
-    get shape() {
-      // return cleaned.value.shape;
-      const _shape = cleaned.value.shape;
-      util.assignProp(this, "shape", _shape);
-      return _shape;
-    },
-    catchall: unknown(),
-    ...util.normalizeParams(params),
-  };
-  return new ZodMiniInterface(def) as any;
-}
+// // looseInterface
+
+// export function looseInterface<T extends core.$ZodLooseShape>(
+//   shape: T,
+//   params?: string | core.$ZodInterfaceParams
+// ): ZodMiniInterface<ProcessInterfaceShape<T>, Record<string, unknown>, Record<string, unknown>> {
+//   const cleaned = util.cached(() => util.cleanInterfaceShape(shape));
+//   const def: core.$ZodInterfaceDef = {
+//     type: "interface",
+//     get shape() {
+//       // return cleaned.value.shape;
+//       const _shape = cleaned.value.shape;
+//       util.assignProp(this, "shape", _shape);
+//       return _shape;
+//     },
+//     // get shapeMeta() {
+//     //   return cleaned.value.shapeMeta;
+//     // },
+//     catchall: unknown(),
+//     ...util.normalizeParams(params),
+//   };
+//   return new ZodMiniInterface(def) as any;
+// }
 
 // ZodMiniObject
 export interface ZodMiniObject<
-  Shape extends core.$ZodShape = core.$ZodShape,
-  Extra extends Record<string, unknown> = Record<string, unknown>,
+  // @ts-ignore Cast variance
+  out Shape extends core.$ZodShape = core.$ZodShape,
+  OutExtra extends Record<string, unknown> = Record<string, unknown>,
+  InExtra extends Record<string, unknown> = Record<string, unknown>,
 > extends ZodMiniType {
-  _zod: core.$ZodObjectInternals<Shape, Extra>;
+  _zod: core.$ZodObjectInternals<Shape, OutExtra, InExtra>;
+  shape: Shape;
 }
 export const ZodMiniObject: core.$constructor<ZodMiniObject> = /*@__PURE__*/ core.$constructor(
   "ZodMiniObject",
@@ -813,13 +818,13 @@ export const ZodMiniObject: core.$constructor<ZodMiniObject> = /*@__PURE__*/ cor
 );
 export function object<T extends core.$ZodShape = Record<never, SomeType>>(
   shape?: T,
-  params?: string | core.$ZodObjectLikeParams
-): ZodMiniObject<T, {}> {
+  params?: string | core.$ZodObjectParams
+): ZodMiniObject<T, {}, {}> {
   const def: core.$ZodObjectDef = {
     type: "object",
-    shape: shape ?? {},
-    get optional() {
-      return util.optionalObjectKeys(shape ?? {});
+    get shape() {
+      util.assignProp(this, "shape", { ...shape });
+      return this.shape;
     },
     ...util.normalizeParams(params),
   };
@@ -831,13 +836,17 @@ export function object<T extends core.$ZodShape = Record<never, SomeType>>(
 export function strictObject<T extends core.$ZodShape>(
   shape: T,
   params?: string | core.$ZodObjectParams
-): ZodMiniObject<T, {}> {
+): ZodMiniObject<T, {}, {}> {
   return new ZodMiniObject({
     type: "object",
-    shape: shape as core.$ZodShape,
-    get optional() {
-      return util.optionalObjectKeys(shape);
+    // shape: shape as core.$ZodShape,
+    get shape() {
+      util.assignProp(this, "shape", { ...shape });
+      return this.shape;
     },
+    // get optional() {
+    //   return util.optionalObjectKeys(shape);
+    // },
     catchall: never(),
     ...util.normalizeParams(params),
   }) as any;
@@ -848,217 +857,215 @@ export function strictObject<T extends core.$ZodShape>(
 export function looseObject<T extends core.$ZodShape>(
   shape: T,
   params?: string | core.$ZodObjectParams
-): ZodMiniObject<T, { [k: string]: unknown }> {
+): ZodMiniObject<T, { [k: string]: unknown }, { [k: string]: unknown }> {
   return new ZodMiniObject({
     type: "object",
-    shape: shape as core.$ZodShape,
-    get optional() {
-      return util.optionalObjectKeys(shape);
+    // shape: shape as core.$ZodShape,
+    get shape() {
+      util.assignProp(this, "shape", { ...shape });
+      return this.shape;
     },
+    // get optional() {
+    //   return util.optionalObjectKeys(shape);
+    // },
     catchall: unknown(),
     ...util.normalizeParams(params),
   }) as any;
 }
 
 // object methods
-export function extend<T extends ZodMiniInterface, U extends ZodMiniInterface>(
-  a: T,
-  b: U
-): ZodMiniInterface<util.Extend<T["_zod"]["def"]["shape"], U["_zod"]["def"]["shape"]>, util.MergeInterfaceParams<T, U>>;
-export function extend<T extends ZodMiniObject, U extends ZodMiniObject>(
-  a: T,
-  b: U
-): ZodMiniObject<
-  util.Extend<T["_zod"]["def"]["shape"], U["_zod"]["def"]["shape"]>,
-  U["_zod"]["extra"] & T["_zod"]["extra"]
->;
-
-export function extend<T extends ZodMiniInterface, U extends core.$ZodLooseShape>(
-  a: T,
-  b: U
-): ZodMiniInterface<util.ExtendInterfaceShape<T["_zod"]["def"]["shape"], U>, util.ExtendInterfaceParams<T, U>>;
 export function extend<T extends ZodMiniObject, U extends core.$ZodLooseShape>(
-  a: T,
-  b: U
-): ZodMiniObject<util.Extend<T["_zod"]["def"]["shape"], U>, T["_zod"]["extra"]>;
-export function extend(schema: ZodMiniObjectLike, shape: any): ZodMiniObjectLike {
+  schema: T,
+  shape: U
+): ZodMiniObject<util.Extend<T["shape"], U>, T["_zod"]["outextra"], T["_zod"]["inextra"]> {
   // console.log({ schema, shape });
-  if (shape instanceof core.$ZodType) return util.mergeObjectLike(schema, shape as any);
-  if (schema instanceof ZodMiniInterface) {
-    return util.mergeObjectLike(schema, _interface(shape));
-  }
-  if (schema instanceof ZodMiniObject) return util.mergeObjectLike(schema, object(shape));
+  // if (shape instanceof core.$ZodType) return util.mergeObjectLike(schema, shape as any);
   return util.extend(schema, shape);
+  // if (schema instanceof ZodMiniInterface) {
+  //   return util.extend(schema, shape);
+  // }
+  // if (schema instanceof ZodMiniObject) return util.mergeObjectLike(schema, object(shape));
+  // return util.extend(schema, shape);
 }
 
-export function merge<T extends ZodMiniObjectLike, U extends core.$ZodLooseShape>(
-  schema: T,
-  shape: U
-): T["_zod"]["def"]["type"] extends "interface"
-  ? ZodMiniInterface<
-      util.Extend<T["_zod"]["def"]["shape"], U["_zod"]["def"]["shape"]>,
-      {
-        extra: T["_zod"]["extra"] & U["_zod"]["extra"];
-        optional: Exclude<T["_zod"]["optional"], keyof U["_zod"]["def"]["shape"]> | U["_zod"]["optional"];
-        defaulted: Exclude<T["_zod"]["defaulted"], keyof U["_zod"]["def"]["shape"]> | U["_zod"]["defaulted"];
-      }
-    >
-  : ZodMiniObject<util.Extend<T["_zod"]["def"]["shape"], U>, T["_zod"]["extra"]>;
-export function merge(a: ZodMiniObjectLike, b: ZodMiniObjectLike): ZodMiniObjectLike {
-  return util.mergeObjectLike(a, b);
+/** @deprecated Identical to `z.extend(A, B)` */
+export function merge<T extends ZodMiniObject, U extends ZodMiniObject>(
+  a: T,
+  b: U
+): ZodMiniObject<util.Extend<T["shape"], U["shape"]>, T["_zod"]["outextra"], T["_zod"]["inextra"]>;
+export function merge(schema: ZodMiniObject, shape: any): ZodMiniObject {
+  return util.extend(schema, shape);
 }
+// export function merge<T extends ZodMiniObjectLike, U extends core.$ZodLooseShape>(
+//   schema: T,
+//   shape: U
+// ): T["_zod"]["def"]["type"] extends "interface"
+//   ? ZodMiniInterface<
+//       util.Extend<T["shape"], U["shape"]>,
+//       {
+//         extra: T["_zod"]["extra"] & U["_zod"]["extra"];
+//         optional: Exclude<T["_zod"]["optional"], keyof U["shape"]> | U["_zod"]["optional"];
+//         defaulted: Exclude<T["_zod"]["defaulted"], keyof U["shape"]> | U["_zod"]["defaulted"];
+//       }
+//     >
+//   : ZodMiniObject<util.Extend<T["shape"], U>, T["_zod"]["extra"]>;
+// export function merge(a: ZodMiniObjectLike, b: ZodMiniObjectLike): ZodMiniObjectLike {
+//   return util.mergeObjectLike(a, b);
+// }
 
 // .pick
-export function pick<
-  T extends ZodMiniObjectLike,
-  M extends util.Exactly<util.Mask<keyof T["_zod"]["def"]["shape"]>, M>,
->(
+// export function pick<T extends ZodMiniInterface, M extends util.Exactly<util.Mask<keyof T["shape"]>, M>>(
+//   schema: T,
+//   mask: M
+// ): ZodMiniInterface<
+//   util.Flatten<Pick<T["shape"], keyof T["shape"] & T["_cleanToRaw"][string & keyof M]>>,
+//   T["_zod"]["outextra"],
+//   T["_zod"]["inextra"]
+// >;
+export function pick<T extends ZodMiniObject, M extends util.Exactly<util.Mask<keyof T["shape"]>, M>>(
   schema: T,
   mask: M
-): T["_zod"]["def"]["type"] extends "interface"
-  ? ZodMiniInterface<
-      util.Flatten<Pick<T["_zod"]["def"]["shape"], keyof T["_zod"]["def"]["shape"] & keyof M>>,
-      {
-        optional: Extract<T["_zod"]["optional"], keyof M>;
-        defaulted: Extract<T["_zod"]["defaulted"], keyof M>;
-        extra: T["_zod"]["extra"];
-      }
-    >
-  : ZodMiniObject<
-      util.Flatten<Pick<T["_zod"]["def"]["shape"], keyof T["_zod"]["def"]["shape"] & keyof M>>,
-      T["_zod"]["extra"]
-    >;
-export function pick(schema: ZodMiniObjectLike, mask: object) {
-  return util.pick(schema, mask);
+): ZodMiniObject<
+  util.Flatten<Pick<T["shape"], keyof T["shape"] & keyof M>>,
+  T["_zod"]["outextra"],
+  T["_zod"]["inextra"]
+> {
+  return util.pick(schema, mask as any);
 }
 
 // .omit
-export function omit<
-  T extends ZodMiniObjectLike,
-  const M extends util.Exactly<util.Mask<keyof T["_zod"]["def"]["shape"]>, M>,
->(
+
+export function omit<T extends ZodMiniObject, const M extends util.Exactly<util.Mask<keyof T["shape"]>, M>>(
   schema: T,
   mask: M
-): T["_zod"]["def"]["type"] extends "interface"
-  ? ZodMiniInterface<
-      util.Flatten<Omit<T["_zod"]["def"]["shape"], keyof M>>,
-      {
-        optional: Exclude<T["_zod"]["optional"], keyof M>;
-        defaulted: Exclude<T["_zod"]["defaulted"], keyof M>;
-        extra: T["_zod"]["extra"];
-      }
-    >
-  : ZodMiniObject<util.Flatten<Omit<T["_zod"]["def"]["shape"], keyof M>>, T["_zod"]["extra"]>;
-
-export function omit(schema: ZodMiniObjectLike, mask: object) {
+): ZodMiniObject<util.Flatten<Omit<T["shape"], keyof M>>, T["_zod"]["outextra"], T["_zod"]["inextra"]> {
   return util.omit(schema, mask);
 }
 
-export function partial<T extends ZodMiniObjectLike>(
+// export type PartialInterfaceShape<
+//   Shape extends core.$ZodLooseShape,
+//   Keys extends PropertyKey = keyof Shape,
+// > = util.Identity<{
+//   [k in keyof Shape as util.CleanKey<k> extends Keys ? `${util.CleanKey<k> & string}?` : k]: Shape[k];
+// }>;
+// export type RequiredInterfaceShape<
+//   Shape extends core.$ZodLooseShape,
+//   Keys extends PropertyKey = keyof Shape,
+// > = util.Identity<
+//   {
+//     [k in keyof Shape as util.CleanKey<k> extends Keys ? util.CleanKey<k> : never]: ZodMiniNonOptional<Shape[k]>;
+//   } & {
+//     [k in keyof Shape as util.CleanKey<k> extends Keys ? never : k]: Shape[k];
+//   }
+// >;
+// export type ExtendInterfaceShape<
+//   Shape extends core.$ZodLooseShape,
+//   Incoming extends core.$ZodLooseShape,
+// > = util.CleanKey<keyof Shape> & util.CleanKey<keyof Incoming> extends never
+//   ? Shape & Incoming
+//   : util.Identity<
+//       {
+//         [k in util.CleanKey<keyof Shape> as util.CleanKey<k> extends util.CleanKey<keyof Incoming>
+//           ? never
+//           : k]: Shape[k];
+//       } & {
+//         [k in keyof Incoming]: Incoming[k];
+//       }
+//     >;
+
+// type Arg = Partial<Record<string, unknown>>;
+
+export function partial<T extends ZodMiniObject>(
   schema: T
-): T["_zod"]["def"]["type"] extends "interface"
-  ? ZodMiniInterface<
-      // T['_zod']["shape"],
-      {
-        [k in keyof T["_zod"]["def"]["shape"]]: ZodMiniOptional<T["_zod"]["def"]["shape"][k]>;
-      },
-      {
-        optional: string & keyof T["_zod"]["def"]["shape"];
-        defaulted: never;
-        extra: T["_zod"]["extra"];
-      }
-    >
-  : ZodMiniObject<
-      {
-        [k in keyof T["_zod"]["def"]["shape"]]: ZodMiniOptional<T["_zod"]["def"]["shape"][k]>;
-      },
-      T["_zod"]["extra"]
-    >;
-export function partial<
-  T extends ZodMiniObjectLike,
-  M extends util.Exactly<util.Mask<keyof T["_zod"]["def"]["shape"]>, M>,
->(
+): ZodMiniObject<
+  {
+    [k in keyof T["shape"]]: ZodMiniOptional<T["shape"][k]>;
+  },
+  T["_zod"]["outextra"],
+  T["_zod"]["inextra"]
+>;
+export function partial<T extends ZodMiniObject, M extends util.Exactly<util.Mask<keyof T["shape"]>, M>>(
   schema: T,
   mask: M
-): T["_zod"]["def"]["type"] extends "interface"
-  ? ZodMiniInterface<
-      util.Extend<
-        T["_zod"]["def"]["shape"],
-        {
-          [k in keyof M & keyof T["_zod"]["def"]["shape"]]: ZodMiniOptional<T["_zod"]["def"]["shape"][k]>;
-        }
-      >,
-      {
-        optional: string & (T["_zod"]["optional"] | keyof M);
-        defaulted: T["_zod"]["defaulted"];
-        extra: T["_zod"]["extra"];
-      }
-    >
-  : ZodMiniObject<
-      {
-        [k in keyof T["_zod"]["def"]["shape"]]: k extends keyof M
-          ? ZodMiniOptional<T["_zod"]["def"]["shape"][k]>
-          : T["_zod"]["def"]["shape"][k];
-      },
-      T["_zod"]["extra"]
-    >;
-
-export function partial(schema: ZodMiniObjectLike, mask?: object): ZodMiniObjectLike {
+): ZodMiniObject<
+  {
+    [k in keyof T["shape"]]: k extends keyof M ? ZodMiniOptional<T["shape"][k]> : T["shape"][k];
+  },
+  T["_zod"]["outextra"],
+  T["_zod"]["inextra"]
+>;
+export function partial(schema: ZodMiniObject, mask?: object) {
   return util.partialObjectLike(ZodMiniOptional, schema, mask);
 }
 
+// export function required<T extends { _zod: { subtype: "interface" } } & ZodMiniInterface>(
+//   schema: T
+// ): ZodMiniInterface<
+//   {
+//     [k in keyof T["shape"]]: ZodMiniNonOptional<T["shape"][k]>;
+//   },
+//   {
+//     optional: never;
+//     defaulted: T["_zod"]["defaulted"];
+//     extra: T["_zod"]["extra"];
+//   }
+// >;
+// export function required<
+//   T extends { _zod: { subtype: "interface" } } & ZodMiniInterface,
+//   M extends util.Mask<keyof T["_zod"]["output"]>,
+// >(
+//   schema: T,
+//   mask: M
+// ): ZodMiniInterface<
+//   util.Extend<
+//     T["shape"],
+//     {
+//       [k in keyof M & keyof T["shape"]]: ZodMiniNonOptional<T["shape"][k]>;
+//     }
+//   >,
+//   {
+//     optional: Exclude<T["_zod"]["optional"], keyof M>;
+//     defaulted: T["_zod"]["defaulted"];
+//     extra: T["_zod"]["extra"];
+//   }
+// >;
+
 // .required
-export function required<T extends { _zod: { subtype: "object" } } & ZodMiniObject>(
-  schema: T
-): ZodMiniObject<{
-  [k in keyof T["_zod"]["def"]["shape"]]: ZodMiniNonOptional<T["_zod"]["def"]["shape"][k]>;
-}>;
-export function required<
-  T extends { _zod: { subtype: "object" } } & ZodMiniObject,
-  M extends util.Exactly<util.Mask<keyof T["_zod"]["def"]["shape"]>, M>,
->(
-  schema: T,
-  mask: M
-): ZodMiniObject<
-  util.Extend<
-    T["_zod"]["def"]["shape"],
-    {
-      [k in keyof M & keyof T["_zod"]["def"]["shape"]]: ZodMiniNonOptional<T["_zod"]["def"]["shape"][k]>;
-    }
-  >
+
+export type RequiredInterfaceShape<
+  Shape extends core.$ZodLooseShape,
+  Keys extends PropertyKey = keyof Shape,
+> = util.Identity<
+  {
+    [k in keyof Shape as k extends Keys ? k : never]: ZodMiniNonOptional<Shape[k]>;
+  } & {
+    [k in keyof Shape as k extends Keys ? never : k]: Shape[k];
+  }
 >;
-export function required<T extends { _zod: { subtype: "interface" } } & ZodMiniInterface>(
+
+export function required<T extends ZodMiniObject>(
   schema: T
-): ZodMiniInterface<
+): ZodMiniObject<
   {
-    [k in keyof T["_zod"]["def"]["shape"]]: ZodMiniNonOptional<T["_zod"]["def"]["shape"][k]>;
+    [k in keyof T["shape"]]: ZodMiniNonOptional<T["shape"][k]>;
   },
-  {
-    optional: never;
-    defaulted: T["_zod"]["defaulted"];
-    extra: T["_zod"]["extra"];
-  }
+  T["_zod"]["outextra"],
+  T["_zod"]["inextra"]
 >;
-export function required<
-  T extends { _zod: { subtype: "interface" } } & ZodMiniInterface,
-  M extends util.Mask<keyof T["_zod"]["output"]>,
->(
+export function required<T extends ZodMiniObject, M extends util.Exactly<util.Mask<keyof T["shape"]>, M>>(
   schema: T,
   mask: M
-): ZodMiniInterface<
+): ZodMiniObject<
   util.Extend<
-    T["_zod"]["def"]["shape"],
+    T["shape"],
     {
-      [k in keyof M & keyof T["_zod"]["def"]["shape"]]: ZodMiniNonOptional<T["_zod"]["def"]["shape"][k]>;
+      [k in keyof M & keyof T["shape"]]: ZodMiniNonOptional<T["shape"][k]>;
     }
   >,
-  {
-    optional: Exclude<T["_zod"]["optional"], keyof M>;
-    defaulted: T["_zod"]["defaulted"];
-    extra: T["_zod"]["extra"];
-  }
+  T["_zod"]["outextra"],
+  T["_zod"]["inextra"]
 >;
-export function required(schema: ZodMiniObjectLike, mask?: object): ZodMiniObjectLike {
+export function required(schema: ZodMiniObject, mask?: object) {
   return util.requiredObjectLike(ZodMiniNonOptional, schema, mask);
 }
 
diff --git a/packages/treeshake/out.js b/packages/treeshake/out.js
index b608b0c0..d2ff0fbc 100644
--- a/packages/treeshake/out.js
+++ b/packages/treeshake/out.js
@@ -46,14 +46,6 @@ function jsonStringifyReplacer(_, value) {
         return value.toString();
     return value;
 }
-function nullish(input) {
-    return input === null || input === undefined;
-}
-function cleanRegex(source) {
-    const start = source.startsWith("^") ? 1 : 0;
-    const end = source.endsWith("$") ? source.length - 1 : source.length;
-    return source.slice(start, end);
-}
 function randomString(length = 10) {
     const chars = "abcdefghijklmnopqrstuvwxyz";
     let str = "";
@@ -64,23 +56,13 @@ function randomString(length = 10) {
 }
 // zod-specific utils
 function clone(inst, def) {
-    return new inst._zod.constr(def);
+    const cl = new inst._zod.constr(def ?? inst._zod.def);
+    if (!def)
+        cl._zod.parent = inst;
+    return cl;
 }
 function normalizeParams(_params) {
-    const params = _params;
-    if (!params)
-        return {};
-    if (typeof params === "string")
-        return { error: () => params };
-    if (params?.message !== undefined) {
-        if (params?.error !== undefined)
-            throw new Error("Cannot specify both `message` and `error` params");
-        params.error = params.message;
-    }
-    delete params.message;
-    if (typeof params.error === "string")
-        return { ...params, error: () => params.error };
-    return params;
+    return {};
 }
 function aborted(x, startIndex = 0) {
     for (let i = startIndex; i < x.issues.length; i++) {
@@ -89,14 +71,6 @@ function aborted(x, startIndex = 0) {
     }
     return false;
 }
-function prefixIssues(path, issues) {
-    return issues.map((iss) => {
-        var _a;
-        (_a = iss).path ?? (_a.path = []);
-        iss.path.unshift(path);
-        return iss;
-    });
-}
 function unwrapMessage(message) {
     return typeof message === "string" ? message : message?.message;
 }
@@ -120,25 +94,6 @@ function finalizeIssue(iss, ctx, config) {
     }
     return full;
 }
-function getLengthableOrigin(input) {
-    if (Array.isArray(input))
-        return "array";
-    if (typeof input === "string")
-        return "string";
-    return "unknown";
-}
-function issue(...args) {
-    const [iss, input, inst] = args;
-    if (typeof iss === "string") {
-        return {
-            message: iss,
-            code: "custom",
-            input,
-            inst,
-        };
-    }
-    return { ...iss };
-}
 
 ////////////////////////    ERROR CLASS   ////////////////////////
 const ZOD_ERROR = Symbol.for("{{zod.error}}");
@@ -156,62 +111,6 @@ class $ZodError {
         return inst?._tag === ZOD_ERROR;
     }
 }
-function flattenError(error, mapper = (issue) => issue.message) {
-    const fieldErrors = {};
-    const formErrors = [];
-    for (const sub of error.issues) {
-        if (sub.path.length > 0) {
-            fieldErrors[sub.path[0]] = fieldErrors[sub.path[0]] || [];
-            fieldErrors[sub.path[0]].push(mapper(sub));
-        }
-        else {
-            formErrors.push(mapper(sub));
-        }
-    }
-    return { formErrors, fieldErrors };
-}
-function formatError(error, _mapper) {
-    const mapper = _mapper ||
-        function (issue) {
-            return issue.message;
-        };
-    const fieldErrors = { _errors: [] };
-    const processError = (error) => {
-        for (const issue of error.issues) {
-            if (issue.code === "invalid_union") {
-                issue.errors.map((issues) => processError({ issues }));
-            }
-            else if (issue.code === "invalid_key") {
-                processError({ issues: issue.issues });
-            }
-            else if (issue.code === "invalid_element") {
-                processError({ issues: issue.issues });
-            }
-            else if (issue.path.length === 0) {
-                fieldErrors._errors.push(mapper(issue));
-            }
-            else {
-                let curr = fieldErrors;
-                let i = 0;
-                while (i < issue.path.length) {
-                    const el = issue.path[i];
-                    const terminal = i === issue.path.length - 1;
-                    if (!terminal) {
-                        curr[el] = curr[el] || { _errors: [] };
-                    }
-                    else {
-                        curr[el] = curr[el] || { _errors: [] };
-                        curr[el]._errors.push(mapper(issue));
-                    }
-                    curr = curr[el];
-                    i++;
-                }
-            }
-        }
-    };
-    processError(error);
-    return fieldErrors;
-}
 
 function _parse(schema, value, _ctx) {
     const ctx = _ctx ? { ..._ctx, async: false } : { async: false };
@@ -263,98 +162,11 @@ async function _safeParseAsync(schema, value, _ctx) {
 
 const boolean$1 = /true|false/i;
 
-// import { $ZodType } from "./schemas.js";
-const $ZodCheck = /*@__PURE__*/ $constructor("$ZodCheck", (inst, def) => {
-    inst._zod ?? (inst._zod = {});
-    inst._zod.def = def;
-});
-const $ZodCheckMaxLength = /*@__PURE__*/ $constructor("$ZodCheckMaxLength", (inst, def) => {
-    $ZodCheck.init(inst, def);
-    inst._zod.when = (payload) => {
-        const val = payload.value;
-        return !nullish(val) && val.length !== undefined;
-    };
-    inst._zod.onattach = (inst) => {
-        const curr = (inst._zod.computed.maximum ?? Number.POSITIVE_INFINITY);
-        if (def.maximum < curr)
-            inst._zod.computed.maximum = def.maximum;
-    };
-    inst._zod.check = (payload) => {
-        const input = payload.value;
-        const length = input.length;
-        if (length <= def.maximum)
-            return;
-        const origin = getLengthableOrigin(input);
-        payload.issues.push({
-            origin,
-            code: "too_big",
-            maximum: def.maximum,
-            input,
-            inst,
-            continue: !def.abort,
-        });
-    };
-});
-const $ZodCheckMinLength = /*@__PURE__*/ $constructor("$ZodCheckMinLength", (inst, def) => {
-    $ZodCheck.init(inst, def);
-    inst._zod.when = (payload) => {
-        const val = payload.value;
-        return !nullish(val) && val.length !== undefined;
-    };
-    inst._zod.onattach = (inst) => {
-        const curr = (inst._zod.computed.minimum ?? Number.NEGATIVE_INFINITY);
-        if (def.minimum > curr)
-            inst._zod.computed.minimum = def.minimum;
-    };
-    inst._zod.check = (payload) => {
-        const input = payload.value;
-        const length = input.length;
-        if (length >= def.minimum)
-            return;
-        const origin = getLengthableOrigin(input);
-        payload.issues.push({
-            origin,
-            code: "too_small",
-            minimum: def.minimum,
-            input,
-            inst,
-            continue: !def.abort,
-        });
-    };
-});
-const $ZodCheckLengthEquals = /*@__PURE__*/ $constructor("$ZodCheckLengthEquals", (inst, def) => {
-    $ZodCheck.init(inst, def);
-    inst._zod.when = (payload) => {
-        const val = payload.value;
-        return !nullish(val) && val.length !== undefined;
-    };
-    inst._zod.onattach = (inst) => {
-        inst._zod.computed.minimum = def.length;
-        inst._zod.computed.maximum = def.length;
-        inst._zod.computed.length = def.length;
-    };
-    inst._zod.check = (payload) => {
-        const input = payload.value;
-        const length = input.length;
-        if (length === def.length)
-            return;
-        const origin = getLengthableOrigin(input);
-        const tooBig = length > def.length;
-        payload.issues.push({
-            origin,
-            ...(tooBig ? { code: "too_big", maximum: def.length } : { code: "too_small", minimum: def.length }),
-            input: payload.value,
-            inst,
-            continue: !def.abort,
-        });
-    };
-});
-const $ZodCheckOverwrite = /*@__PURE__*/ $constructor("$ZodCheckOverwrite", (inst, def) => {
-    $ZodCheck.init(inst, def);
-    inst._zod.check = (payload) => {
-        payload.value = def.tx(payload.value);
-    };
-});
+const version = {
+    major: 0,
+    minor: 8,
+    patch: 1,
+};
 
 const $ZodType = /*@__PURE__*/ $constructor("$ZodType", (inst, def) => {
     var _a;
@@ -362,6 +174,8 @@ const $ZodType = /*@__PURE__*/ $constructor("$ZodType", (inst, def) => {
     inst._zod.id = def.type + "_" + randomString(10);
     inst._zod.def = def; // set _def property
     inst._zod.computed = inst._zod.computed || {}; // initialize _computed object
+    inst._zod.version = version;
+    // inst._zod.optionality ??= "required"; // default
     const checks = [...(inst._zod.def.checks ?? [])];
     // if inst is itself a checks.$ZodCheck, run it as a check
     if (inst._zod.traits.has("$ZodCheck")) {
@@ -369,7 +183,9 @@ const $ZodType = /*@__PURE__*/ $constructor("$ZodType", (inst, def) => {
     }
     //
     for (const ch of checks) {
-        ch._zod.onattach?.(inst);
+        for (const fn of ch._zod.onattach) {
+            fn(inst);
+        }
     }
     if (checks.length === 0) {
         // deferred initializer
@@ -400,8 +216,7 @@ const $ZodType = /*@__PURE__*/ $constructor("$ZodType", (inst, def) => {
                     throw new $ZodAsyncError();
                 }
                 if (asyncResult || _ instanceof Promise) {
-                    asyncResult = asyncResult ?? Promise.resolve();
-                    asyncResult.then(async () => {
+                    asyncResult = (asyncResult ?? Promise.resolve()).then(async () => {
                         await _;
                         const nextLen = payload.issues.length;
                         if (nextLen === currLen)
@@ -442,12 +257,12 @@ const $ZodType = /*@__PURE__*/ $constructor("$ZodType", (inst, def) => {
                 return result.then(({ issues, value }) => {
                     if (issues.length === 0)
                         return { value };
-                    return { issues };
+                    return { issues: issues.map((iss) => finalizeIssue(iss, {}, config())) };
                 });
             }
             if (result.issues.length === 0)
                 return { value: result.value };
-            return { issues: result.issues };
+            return { issues: result.issues.map((iss) => finalizeIssue(iss, {}, config())) };
         },
         vendor: "zod",
         version: 1,
@@ -474,682 +289,52 @@ const $ZodBoolean = /*@__PURE__*/ $constructor("$ZodBoolean", (inst, def) => {
         return payload;
     };
 });
-function handleArrayResult(result, final, index) {
-    if (result.issues.length) {
-        final.issues.push(...prefixIssues(index, result.issues));
-    }
-    final.value[index] = result.value;
-}
-const $ZodArray = /*@__PURE__*/ $constructor("$ZodArray", (inst, def) => {
-    $ZodType.init(inst, def);
-    inst._zod.parse = (payload, ctx) => {
-        const input = payload.value;
-        if (!Array.isArray(input)) {
-            payload.issues.push({
-                expected: "array",
-                code: "invalid_type",
-                input,
-                inst,
-            });
-            return payload;
-        }
-        payload.value = Array(input.length);
-        const proms = [];
-        for (let i = 0; i < input.length; i++) {
-            const item = input[i];
-            const result = def.element._zod.run({
-                value: item,
-                issues: [],
-            }, ctx);
-            if (result instanceof Promise) {
-                proms.push(result.then((result) => handleArrayResult(result, payload, i)));
-            }
-            else {
-                handleArrayResult(result, payload, i);
-            }
-        }
-        if (proms.length) {
-            return Promise.all(proms).then(() => payload);
-        }
-        return payload; //handleArrayResultsAsync(parseResults, final);
-    };
-});
-function handleUnionResults(results, final, inst, ctx) {
-    for (const result of results) {
-        if (result.issues.length === 0) {
-            final.value = result.value;
-            return final;
-        }
-    }
-    final.issues.push({
-        code: "invalid_union",
-        input: final.value,
-        inst,
-        errors: results.map((result) => result.issues.map((iss) => finalizeIssue(iss, ctx, config()))),
-    });
-    return final;
-}
-const $ZodUnion = /*@__PURE__*/ $constructor("$ZodUnion", (inst, def) => {
-    $ZodType.init(inst, def);
-    const values = new Set();
-    if (def.options.every((o) => o._zod.values)) {
-        for (const option of def.options) {
-            for (const v of option._zod.values) {
-                values.add(v);
-            }
-        }
-        inst._zod.values = values;
-    }
-    // computed union regex for pattern if all options have pattern
-    if (def.options.every((o) => o._zod.pattern)) {
-        const patterns = def.options.map((o) => o._zod.pattern);
-        inst._zod.pattern = new RegExp(`^(${patterns.map((p) => cleanRegex(p.source)).join("|")})$`);
-    }
-    inst._zod.parse = (payload, ctx) => {
-        const results = [];
-        for (const option of def.options) {
-            const result = option._zod.run({
-                value: payload.value,
-                issues: [],
-            }, ctx);
-            if (result instanceof Promise) {
-                results.push(result);
-            }
-            else {
-                if (result.issues.length === 0)
-                    return result;
-                results.push(result);
-            }
-        }
-        return handleUnionResults(results, payload, inst, ctx);
-    };
-});
-const $ZodTransform = /*@__PURE__*/ $constructor("$ZodTransform", (inst, def) => {
-    $ZodType.init(inst, def);
-    inst._zod.parse = (payload, _ctx) => {
-        const _out = def.transform(payload.value, payload);
-        if (_ctx.async) {
-            const output = _out instanceof Promise ? _out : Promise.resolve(_out);
-            return output.then((output) => {
-                payload.value = output;
-                return payload;
-            });
-        }
-        if (_out instanceof Promise) {
-            throw new $ZodAsyncError();
-        }
-        payload.value = _out;
-        return payload;
-    };
-});
-const $ZodOptional = /*@__PURE__*/ $constructor("$ZodOptional", (inst, def) => {
-    $ZodType.init(inst, def);
-    // inst._zod.qin = "true";
-    inst._zod.qout = "true";
-    if (def.innerType._zod.values)
-        inst._zod.values = new Set([...def.innerType._zod.values, undefined]);
-    const pattern = def.innerType._zod.pattern;
-    if (pattern)
-        inst._zod.pattern = new RegExp(`^(${cleanRegex(pattern.source)})?$`);
-    inst._zod.parse = (payload, ctx) => {
-        if (payload.value === undefined) {
-            return payload;
-        }
-        return def.innerType._zod.run(payload, ctx);
-    };
-});
-const $ZodNullable = /*@__PURE__*/ $constructor("$ZodNullable", (inst, def) => {
-    $ZodType.init(inst, def);
-    inst._zod.qin = def.innerType._zod.qin;
-    inst._zod.qout = def.innerType._zod.qout;
-    const pattern = def.innerType._zod.pattern;
-    if (pattern)
-        inst._zod.pattern = new RegExp(`^(${cleanRegex(pattern.source)}|null)$`);
-    if (def.innerType._zod.values)
-        inst._zod.values = new Set([...def.innerType._zod.values, null]);
-    inst._zod.parse = (payload, ctx) => {
-        if (payload.value === null)
-            return payload;
-        return def.innerType._zod.run(payload, ctx);
-    };
-});
-const $ZodDefault = /*@__PURE__*/ $constructor("$ZodDefault", (inst, def) => {
-    $ZodType.init(inst, def);
-    inst._zod.values = def.innerType._zod.values;
-    inst._zod.parse = (payload, ctx) => {
-        if (payload.value === undefined) {
-            payload.value = def.defaultValue();
-            /**
-             * $ZodDefault always returns the default value immediately.
-             * It doesn't pass the default value into the validator ("prefault"). There's no reason to pass the default value through validation. The validity of the default is enforced by TypeScript statically. Otherwise, it's the responsibility of the user to ensure the default is valid. In the case of pipes with divergent in/out types, you can specify the default on the `in` schema of your ZodPipe to set a "prefault" for the pipe.   */
-            return payload;
-        }
-        const result = def.innerType._zod.run(payload, ctx);
-        if (result instanceof Promise) {
-            return result.then((result) => handleDefaultResult(result, def));
-        }
-        return handleDefaultResult(result, def);
-    };
-});
-function handleDefaultResult(payload, def) {
-    if (payload.value === undefined) {
-        payload.value = def.defaultValue();
-    }
-    return payload;
-}
-const $ZodNonOptional = /*@__PURE__*/ $constructor("$ZodNonOptional", (inst, def) => {
-    $ZodType.init(inst, def);
-    if (def.innerType._zod.values)
-        inst._zod.values = new Set([...def.innerType._zod.values].filter((x) => x !== undefined));
-    inst._zod.parse = (payload, ctx) => {
-        const result = def.innerType._zod.run(payload, ctx);
-        if (result instanceof Promise) {
-            return result.then((result) => handleNonOptionalResult(result, inst));
-        }
-        return handleNonOptionalResult(result, inst);
-    };
-});
-function handleNonOptionalResult(payload, inst) {
-    if (!payload.issues.length && payload.value === undefined) {
-        payload.issues.push({
-            code: "invalid_type",
-            expected: "nonoptional",
-            input: payload.value,
-            inst,
-        });
-    }
-    return payload;
-}
-const $ZodCatch = /*@__PURE__*/ $constructor("$ZodCatch", (inst, def) => {
-    $ZodType.init(inst, def);
-    // inst._zod.qin = def.innerType._zod.qin;
-    inst._zod.qout = def.innerType._zod.qout;
-    inst._zod.values = def.innerType._zod.values;
-    inst._zod.parse = (payload, ctx) => {
-        const result = def.innerType._zod.run(payload, ctx);
-        if (result instanceof Promise) {
-            return result.then((result) => {
-                if (result.issues.length) {
-                    payload.value = def.catchValue({
-                        ...payload,
-                        error: { issues: result.issues.map((iss) => finalizeIssue(iss, ctx, config())) },
-                        input: payload.value,
-                    });
-                    payload.issues = [];
-                }
-                else {
-                    payload.value = result.value;
-                }
-                return payload;
-            });
-        }
-        if (result.issues.length) {
-            payload.value = def.catchValue({
-                ...payload,
-                error: { issues: result.issues.map((iss) => finalizeIssue(iss, ctx, config())) },
-                input: payload.value,
-            });
-            payload.issues = [];
-        }
-        else {
-            payload.value = result.value;
-        }
-        return payload;
-    };
-});
-const $ZodPipe = /*@__PURE__*/ $constructor("$ZodPipe", (inst, def) => {
-    $ZodType.init(inst, def);
-    // inst._zod.qin = def.in._zod.qin;
-    // inst._zod.qout = def.in._zod.qout;
-    inst._zod.values = def.in._zod.values;
-    inst._zod.parse = (payload, ctx) => {
-        const left = def.in._zod.run(payload, ctx);
-        if (left instanceof Promise) {
-            return left.then((left) => handlePipeResult(left, def, ctx));
-        }
-        return handlePipeResult(left, def, ctx);
-    };
-});
-function handlePipeResult(left, def, ctx) {
-    if (aborted(left)) {
-        return left;
-    }
-    return def.out._zod.run({ value: left.value, issues: left.issues }, ctx);
-}
-const $ZodReadonly = /*@__PURE__*/ $constructor("$ZodReadonly", (inst, def) => {
-    $ZodType.init(inst, def);
-    // inst._zod.qin = def.innerType._zod.qin;
-    inst._zod.qout = def.innerType._zod.qout;
-    inst._zod.parse = (payload, ctx) => {
-        const result = def.innerType._zod.run(payload, ctx);
-        if (result instanceof Promise) {
-            return result.then(handleReadonlyResult);
-        }
-        return handleReadonlyResult(result);
-    };
-});
-function handleReadonlyResult(payload) {
-    payload.value = Object.freeze(payload.value);
-    return payload;
-}
-const $ZodCustom = /*@__PURE__*/ $constructor("$ZodCustom", (inst, def) => {
-    // if (def.checks?.length) console.warn("Can't add custom checks to z.custom()");
-    $ZodCheck.init(inst, def);
-    $ZodType.init(inst, def);
-    inst._zod.parse = (payload, _) => {
-        return payload;
-    };
-    inst._zod.check = (payload) => {
-        const input = payload.value;
-        const r = def.fn(input);
-        if (r instanceof Promise) {
-            return r.then((r) => handleRefineResult(r, payload, input, inst));
-        }
-        handleRefineResult(r, payload, input, inst);
-        return;
-    };
-});
-function handleRefineResult(result, payload, input, inst) {
-    if (!result) {
-        const _iss = {
-            code: "custom",
-            input,
-            inst, // incorporates params.error into issue reporting
-            path: inst._zod.def.path, // incorporates params.error into issue reporting
-            continue: !inst._zod.def.abort,
-            // params: inst._zod.def.params,
-        };
-        if (inst._zod.def.params)
-            _iss.params = inst._zod.def.params;
-        payload.issues.push(issue(_iss));
-    }
-}
-
-class $ZodRegistry {
-    constructor() {
-        this._map = new WeakMap();
-        this._idmap = new Map();
-    }
-    add(schema, ..._meta) {
-        const meta = _meta[0];
-        this._map.set(schema, meta);
-        if (meta && typeof meta === "object" && "id" in meta) {
-            if (this._idmap.has(meta.id)) {
-                throw new Error(`ID ${meta.id} already exists in the registry`);
-            }
-            this._idmap.set(meta.id, schema);
-        }
-        return this;
-    }
-    remove(schema) {
-        this._map.delete(schema);
-        return this;
-    }
-    get(schema) {
-        return this._map.get(schema);
-    }
-    has(schema) {
-        return this._map.has(schema);
-    }
-}
-class $ZodJSONSchemaRegistry extends $ZodRegistry {
-    toJSONSchema(_schema) {
-        return {};
-    }
-}
-const globalRegistry = 
-/*@__PURE__*/ new $ZodJSONSchemaRegistry();
 
 function _boolean(Class, params) {
     return new Class({
         type: "boolean",
-        ...normalizeParams(params),
-    });
-}
-function _maxLength(maximum, params) {
-    const ch = new $ZodCheckMaxLength({
-        check: "max_length",
-        ...normalizeParams(params),
-        maximum,
-    });
-    return ch;
-}
-function _minLength(minimum, params) {
-    return new $ZodCheckMinLength({
-        check: "min_length",
-        ...normalizeParams(params),
-        minimum,
-    });
-}
-function _length(length, params) {
-    return new $ZodCheckLengthEquals({
-        check: "length_equals",
-        ...normalizeParams(params),
-        length,
-    });
-}
-function _overwrite(tx) {
-    return new $ZodCheckOverwrite({
-        check: "overwrite",
-        tx,
+        ...normalizeParams(),
     });
 }
-function _array(Class, element, params) {
-    return new Class({
-        type: "array",
-        element,
-        // get element() {
-        //   return element;
-        // },
-        ...normalizeParams(params),
-    });
-}
-function _custom(Class, fn, _params) {
-    const schema = new Class({
-        type: "custom",
-        check: "custom",
-        fn: fn,
-        ...normalizeParams(_params),
-    });
-    return schema;
-}
 
-class ZodError extends $ZodError {
-    format(mapper) {
-        return formatError(this, mapper);
-    }
-    flatten(mapper) {
-        return flattenError(this, mapper);
-    }
-    /** @deprecated Push directly to `.issues` instead. */
-    addIssue(issue) {
-        this.issues.push(issue);
-    }
-    /** @deprecated Push directly to `.issues` instead. */
-    addIssues(issues) {
-        this.issues.push(...issues);
-    }
-    /** @deprecated Check `err.issues.length === 0` instead. */
-    get isEmpty() {
-        return this.issues.length === 0;
-    }
-}
-// /** @deprecated Use `z.core.$ZodErrorMapCtx` instead. */
-// export type ErrorMapCtx = core.$ZodErrorMapCtx;
-
-const parse = /* @__PURE__ */ _parse.bind({ Error: ZodError });
-const safeParse = /* @__PURE__ */ _safeParse.bind({ Error: ZodError });
-const parseAsync = /* @__PURE__ */ _parseAsync.bind({ Error: ZodError });
+const parse = /* @__PURE__ */ _parse.bind({ Error: $ZodError });
+const safeParse = /* @__PURE__ */ _safeParse.bind({ Error: $ZodError });
+const parseAsync = /* @__PURE__ */ _parseAsync.bind({ Error: $ZodError });
 const safeParseAsync = /* @__PURE__ */ _safeParseAsync.bind({
-    Error: ZodError,
+    Error: $ZodError,
 });
 
-const ZodType = /*@__PURE__*/ $constructor("ZodType", (inst, def) => {
+const ZodMiniType = /*@__PURE__*/ $constructor("ZodMiniType", (inst, def) => {
+    if (!inst._zod)
+        throw new Error("Uninitialized schema in mixin ZodMiniType.");
     $ZodType.init(inst, def);
     inst.def = def;
-    inst._def = def;
-    // base methods
+    inst.parse = (data, params) => parse(inst, data, params);
+    inst.safeParse = (data, params) => safeParse(inst, data, params);
+    inst.parseAsync = async (data, params) => parseAsync(inst, data, params);
+    inst.safeParseAsync = async (data, params) => safeParseAsync(inst, data, params);
     inst.check = (...checks) => {
         return inst.clone({
             ...def,
             checks: [
                 ...(def.checks ?? []),
-                ...checks.map((ch) => (typeof ch === "function" ? { _zod: { check: ch, def: { check: "custom" } } } : ch)),
+                ...checks.map((ch) => typeof ch === "function" ? { _zod: { check: ch, def: { check: "custom" }, onattach: [] } } : ch),
             ],
         });
     };
-    inst.clone = (_def) => clone(inst, _def ?? def);
+    inst.clone = (_def) => clone(inst, _def);
     inst.brand = () => inst;
     inst.register = ((reg, meta) => {
         reg.add(inst, meta);
         return inst;
     });
-    // parsing
-    inst.parse = (data, params) => parse(inst, data, params);
-    inst.safeParse = (data, params) => safeParse(inst, data, params);
-    inst.parseAsync = async (data, params) => parseAsync(inst, data, params);
-    inst.safeParseAsync = async (data, params) => safeParseAsync(inst, data, params);
-    inst.spa = inst.safeParseAsync;
-    // refinements
-    inst.refine = (check, params) => inst.check(refine(check, params));
-    inst.superRefine = (refinement) => inst.check(superRefine(refinement));
-    inst.overwrite = (fn) => inst.check(_overwrite(fn));
-    // wrappers
-    inst.optional = (params) => optional(inst, params);
-    inst.nullable = (params) => nullable(inst, params);
-    inst.nullish = () => optional(nullable(inst));
-    inst.nonoptional = (params) => nonoptional(inst, params);
-    inst.array = () => array(inst);
-    inst.or = (arg) => union([inst, arg]);
-    // inst.and = (arg) => intersection(inst, arg);
-    inst.transform = (tx) => pipe(inst, transform(tx));
-    inst.default = (def, params) => _default(inst, def, params);
-    // inst.coalesce = (def, params) => coalesce(inst, def, params);
-    inst.catch = (params) => _catch(inst, params);
-    inst.pipe = (target) => pipe(inst, target);
-    inst.readonly = () => readonly(inst);
-    // meta
-    inst.describe = (description) => {
-        const cl = inst.clone();
-        const meta = globalRegistry.get(inst) ?? {};
-        meta.description = description;
-        globalRegistry.add(cl, meta);
-        return cl;
-    };
-    Object.defineProperty(inst, "description", {
-        get() {
-            return globalRegistry.get(inst)?.description;
-        },
-        configurable: true,
-    });
-    inst.meta = (...args) => {
-        if (args.length === 0)
-            return globalRegistry.get(inst);
-        const cl = inst.clone();
-        globalRegistry.add(cl, args[0]);
-        return cl;
-    };
-    // helpers
-    inst.isOptional = () => inst.safeParse(undefined).success;
-    inst.isNullable = () => inst.safeParse(null).success;
-    return inst;
 });
-const ZodBoolean = /*@__PURE__*/ $constructor("ZodBoolean", (inst, def) => {
+const ZodMiniBoolean = /*@__PURE__*/ $constructor("ZodMiniBoolean", (inst, def) => {
     $ZodBoolean.init(inst, def);
-    ZodType.init(inst, def);
+    ZodMiniType.init(inst, def);
 });
 function boolean(params) {
-    return _boolean(ZodBoolean, params);
-}
-const ZodArray = /*@__PURE__*/ $constructor("ZodArray", (inst, def) => {
-    $ZodArray.init(inst, def);
-    ZodType.init(inst, def);
-    inst.element = def.element;
-    inst.min = (minLength, params) => inst.check(_minLength(minLength, params));
-    inst.nonempty = (params) => inst.check(_minLength(1, params));
-    inst.max = (maxLength, params) => inst.check(_maxLength(maxLength, params));
-    inst.length = (len, params) => inst.check(_length(len, params));
-});
-function array(element, params) {
-    return _array(ZodArray, element, params);
-}
-const ZodUnion = /*@__PURE__*/ $constructor("ZodUnion", (inst, def) => {
-    $ZodUnion.init(inst, def);
-    ZodType.init(inst, def);
-    inst.options = def.options;
-});
-function union(options, params) {
-    return new ZodUnion({
-        type: "union",
-        options,
-        ...normalizeParams(params),
-    });
-}
-const ZodTransform = /*@__PURE__*/ $constructor("ZodTransform", (inst, def) => {
-    $ZodTransform.init(inst, def);
-    ZodType.init(inst, def);
-    inst._zod.parse = (payload, _ctx) => {
-        payload.addIssue = (issue$1) => {
-            if (typeof issue$1 === "string") {
-                payload.issues.push(issue(issue$1, payload.value, def));
-            }
-            else {
-                // for Zod 3 backwards compatibility
-                const _issue = issue$1;
-                if (_issue.fatal)
-                    _issue.continue = false;
-                _issue.code ?? (_issue.code = "custom");
-                _issue.input ?? (_issue.input = payload.value);
-                _issue.inst ?? (_issue.inst = inst);
-                _issue.continue ?? (_issue.continue = !def.abort);
-                payload.issues.push(issue(_issue));
-            }
-        };
-        const output = def.transform(payload.value, payload);
-        if (output instanceof Promise) {
-            return output.then((output) => {
-                payload.value = output;
-                return payload;
-            });
-        }
-        payload.value = output;
-        return payload;
-    };
-});
-function transform(fn, params) {
-    return new ZodTransform({
-        type: "transform",
-        transform: fn,
-        ...normalizeParams(params),
-    });
-}
-const ZodOptional = /*@__PURE__*/ $constructor("ZodOptional", (inst, def) => {
-    $ZodOptional.init(inst, def);
-    ZodType.init(inst, def);
-    inst.unwrap = () => inst._zod.def.innerType;
-});
-function optional(innerType, params) {
-    return new ZodOptional({
-        type: "optional",
-        innerType,
-        ...normalizeParams(params),
-    });
-}
-const ZodNullable = /*@__PURE__*/ $constructor("ZodNullable", (inst, def) => {
-    $ZodNullable.init(inst, def);
-    ZodType.init(inst, def);
-    inst.unwrap = () => inst._zod.def.innerType;
-});
-function nullable(innerType, params) {
-    return new ZodNullable({
-        type: "nullable",
-        innerType,
-        ...normalizeParams(params),
-    });
-}
-const ZodDefault = /*@__PURE__*/ $constructor("ZodDefault", (inst, def) => {
-    $ZodDefault.init(inst, def);
-    ZodType.init(inst, def);
-    inst.unwrap = () => inst._zod.def.innerType;
-    inst.removeDefault = inst.unwrap;
-});
-function _default(innerType, defaultValue, params) {
-    return new ZodDefault({
-        type: "default",
-        defaultValue: (typeof defaultValue === "function" ? defaultValue : () => defaultValue),
-        innerType,
-        ...normalizeParams(params),
-    });
-}
-const ZodNonOptional = /*@__PURE__*/ $constructor("ZodNonOptional", (inst, def) => {
-    $ZodNonOptional.init(inst, def);
-    ZodType.init(inst, def);
-    inst.unwrap = () => inst._zod.def.innerType;
-});
-function nonoptional(innerType, params) {
-    return new ZodNonOptional({
-        type: "nonoptional",
-        innerType,
-        ...normalizeParams(params),
-    });
-}
-const ZodCatch = /*@__PURE__*/ $constructor("ZodCatch", (inst, def) => {
-    $ZodCatch.init(inst, def);
-    ZodType.init(inst, def);
-    inst.unwrap = () => inst._zod.def.innerType;
-    inst.removeCatch = inst.unwrap;
-});
-function _catch(innerType, catchValue, params) {
-    return new ZodCatch({
-        type: "catch",
-        innerType,
-        catchValue: (typeof catchValue === "function" ? catchValue : () => catchValue),
-        ...normalizeParams(params),
-    });
-}
-const ZodPipe = /*@__PURE__*/ $constructor("ZodPipe", (inst, def) => {
-    $ZodPipe.init(inst, def);
-    ZodType.init(inst, def);
-    inst.in = def.in;
-    inst.out = def.out;
-});
-function pipe(in_, out, params) {
-    return new ZodPipe({
-        type: "pipe",
-        in: in_,
-        out,
-        ...normalizeParams(params),
-    });
-}
-const ZodReadonly = /*@__PURE__*/ $constructor("ZodReadonly", (inst, def) => {
-    $ZodReadonly.init(inst, def);
-    ZodType.init(inst, def);
-});
-function readonly(innerType, params) {
-    return new ZodReadonly({
-        type: "readonly",
-        innerType,
-        ...normalizeParams(params),
-    });
-}
-const ZodCustom = /*@__PURE__*/ $constructor("ZodCustom", (inst, def) => {
-    $ZodCustom.init(inst, def);
-    ZodType.init(inst, def);
-});
-// custom checks
-function check(fn, params) {
-    const ch = new $ZodCheck({
-        check: "custom",
-        ...normalizeParams(params),
-    });
-    ch._zod.check = fn;
-    return ch;
-}
-function refine(fn, _params = {}) {
-    return _custom(ZodCustom, fn, _params);
-}
-// superRefine
-function superRefine(fn, params) {
-    const ch = check((payload) => {
-        payload.addIssue = (issue$1) => {
-            if (typeof issue$1 === "string") {
-                payload.issues.push(issue(issue$1, payload.value, ch._zod.def));
-            }
-            else {
-                // for Zod 3 backwards compatibility
-                const _issue = issue$1;
-                if (_issue.fatal)
-                    _issue.continue = false;
-                _issue.code ?? (_issue.code = "custom");
-                _issue.input ?? (_issue.input = payload.value);
-                _issue.inst ?? (_issue.inst = ch);
-                _issue.continue ?? (_issue.continue = !ch._zod.def.abort);
-                payload.issues.push(issue(_issue));
-            }
-        };
-        return fn(payload.value, payload);
-    }, params);
-    return ch;
+    return _boolean(ZodMiniBoolean);
 }
 
 var schema = boolean();
diff --git a/packages/tsc/bisect.ts b/packages/tsc/bisect.ts
index 07e87728..179a681e 100644
--- a/packages/tsc/bisect.ts
+++ b/packages/tsc/bisect.ts
@@ -48,7 +48,7 @@ while (!MAX || MAX - MIN > 2) {
   //   numRefs: 1,
   // });
   gen.generateExtendChain({
-    ...gen.ZOD,
+    ...gen.ARKTYPE,
     numSchemas: CURR,
     numKeys: 6,
   });
diff --git a/packages/tsc/generate.ts b/packages/tsc/generate.ts
index 4a160e61..ebe7b547 100644
--- a/packages/tsc/generate.ts
+++ b/packages/tsc/generate.ts
@@ -25,8 +25,8 @@ export const ARKTYPE = {
 };
 
 generateExtendChain({
-  ...ZOD,
-  numSchemas: 40,
+  ...ARKTYPE,
+  numSchemas: 25,
   numKeys: 6,
 });
 // generate({
diff --git a/packages/tsc/package.json b/packages/tsc/package.json
index d217d851..140de49b 100644
--- a/packages/tsc/package.json
+++ b/packages/tsc/package.json
@@ -8,13 +8,13 @@
   "devDependencies": {
     "@types/node": "^22.10.5",
     "@typescript/analyze-trace": "^0.10.1",
-    "arktype": "2.0.0-rc.33",
+    "arktype": "^2.0.0",
     "valibot": "^1.0.0",
     "zod": "workspace:*",
     "@zod/core": "workspace:*",
     "zod3-24-2": "npm:zod@3.24.2",
     "zod3-24-3": "npm:zod@3.24.3",
-    "zod4": "npm:zod@4.0.0-beta.20250415T232143",
+    "zod4": "npm:zod@4.0.0-beta.20250420T053007",
     "zod3": "npm:zod@^3.0.0",
     "@zod/mini": "workspace:*",
     "execa": "^9.5.2"
diff --git a/packages/zod/src/schemas.ts b/packages/zod/src/schemas.ts
index d7ec6630..ee396073 100644
--- a/packages/zod/src/schemas.ts
+++ b/packages/zod/src/schemas.ts
@@ -1,5 +1,6 @@
 import * as core from "@zod/core";
 import { util } from "@zod/core";
+
 import * as checks from "./checks.js";
 import * as iso from "./iso.js";
 import * as parse from "./parse.js";
@@ -23,12 +24,12 @@ export interface ZodType<out Output = unknown, out Input = unknown> extends core
   def: this["_zod"]["def"];
   /** @deprecated Use `.def` instead. */
   _def: this["_zod"]["def"];
-  /** @deprecated Use `z.output<typeof schema>` instead. */
-  _output: this["_zod"]["output"];
-  /** @deprecated Use `z.input<typeof schema>` instead. */
-  _input: this["_zod"]["input"];
+  // /** @deprecated Use `z.output<typeof schema>` instead. */
+  _output: core.output<this>;
+  // /** @deprecated Use `z.input<typeof schema>` instead. */
+  _input: core.input<this>;
   // base methods
-  check(...checks: (core.CheckFn<this["_zod"]["output"]> | core.$ZodCheck<this["_zod"]["output"]>)[]): this;
+  check(...checks: (core.CheckFn<core.output<this>> | core.$ZodCheck<core.output<this>>)[]): this;
   clone(def?: this["_zod"]["def"]): this;
   register<R extends core.$ZodRegistry>(
     registry: R,
@@ -38,9 +39,10 @@ export interface ZodType<out Output = unknown, out Input = unknown> extends core
         : [core.$ZodRegistry<R["_meta"], this>["_meta"]]
       : ["Incompatible schema"]
   ): this;
+
   brand<T extends PropertyKey = PropertyKey>(
     value?: T
-  ): this & Record<"_zod", Record<"output", this["_zod"]["output"] & core.$brand<T>>>;
+  ): PropertyKey extends T ? this : this & Record<"_zod", Record<"~output", core.output<this> & core.$brand<T>>>;
 
   // parsing
   parse(data: unknown, params?: core.ParseContext<core.$ZodIssue>): core.output<this>;
@@ -1007,257 +1009,305 @@ export function array<T extends core.$ZodType>(element: core.$ZodType, params?:
 }
 
 // ZodObjectLike
-export interface ZodObjectLike<out O = object, out I = object> extends ZodType {
-  _zod: core.$ZodObjectLikeInternals<O, I>;
-}
-export const ZodObjectLike: core.$constructor<ZodObjectLike> = /*@__PURE__*/ core.$constructor(
-  "ZodObjectLike",
-  (inst, def) => {
-    core.$ZodObjectLike.init(inst, def);
-    ZodType.init(inst, def);
-  }
-);
+// export interface ZodObjectLike<out O extends object = object, out I extends object = object> extends ZodType {
+//   _zod: core.$ZodObjectLikeInternals<O, I>;
+// }
+// export const ZodObject: core.$constructor<ZodObjectLike> = /*@__PURE__*/ core.$constructor(
+//   "ZodObjectLike",
+//   (inst, def) => {
+//     core.$ZodObject.init(inst, def);
+//     ZodType.init(inst, def);
+//   }
+// );
 
 // .keyof
-export function keyof<T extends ZodObject>(schema: T): ZodLiteral<keyof T["_zod"]["def"]["shape"]>;
-export function keyof<T extends ZodInterface>(schema: T): ZodLiteral<keyof T["_zod"]["output"]>;
-export function keyof(schema: ZodObjectLike) {
-  const shape =
-    schema._zod.def.type === "interface"
-      ? util.cleanInterfaceShape(schema._zod.def.shape).shape
-      : schema._zod.def.shape;
-
+export function keyof<T extends ZodObject>(schema: T): ZodLiteral<keyof T["_zod"]["output"]> {
+  const shape = schema._zod.def.shape;
   return literal(Object.keys(shape)) as any;
 }
 
 // ZodInterface
-type ZodInterfacePartial<
-  T extends ZodInterface,
-  Keys extends keyof T["_zod"]["def"]["shape"] = keyof T["_zod"]["def"]["shape"],
-> = ZodInterface<
-  util.Extend<
-    T["_zod"]["def"]["shape"],
-    {
-      [k in Keys]: ZodOptional<T["_zod"]["def"]["shape"][k]>;
-    }
-  >,
-  {
-    optional: T["_zod"]["optional"] | (string & Keys);
-    defaulted: T["_zod"]["defaulted"];
-    extra: T["_zod"]["extra"];
-  }
->;
-
-type ZodInterfaceRequired<
-  T extends ZodInterface,
-  Keys extends keyof T["_zod"]["def"]["shape"] = keyof T["_zod"]["def"]["shape"],
-> = ZodInterface<
-  util.Extend<
-    T["_zod"]["def"]["shape"],
-    {
-      [k in Keys]: ZodNonOptional<T["_zod"]["def"]["shape"][k]>;
-    }
-  >,
-  {
-    optional: never;
-    defaulted: T["_zod"]["defaulted"];
-    extra: T["_zod"]["extra"];
-  }
->;
-
-export type MergeInterfaces<A extends ZodInterface, B extends ZodInterface> = ZodInterface<
-  util.Extend<A["_zod"]["def"]["shape"], B["_zod"]["def"]["shape"]>,
-  util.MergeInterfaceParams<A, B>
->;
-
-export interface ZodInterface<
-  // @ts-ignore cast variance
-  out Shape extends core.$ZodLooseShape = core.$ZodLooseShape,
-  // @ts-ignore cast variance
-  out Params extends core.$ZodInterfaceNamedParams = core.$ZodInterfaceNamedParams,
-> extends ZodType {
-  _zod: core.$ZodInterfaceInternals<Shape, Params>;
-
-  keyof(): ZodEnum<util.ToEnum<util.InterfaceKeys<string & keyof Shape>>>;
-  catchall<T extends core.$ZodType>(
-    schema: T
-  ): ZodInterface<
-    Shape,
-    {
-      optional: Params["optional"];
-      defaulted: Params["defaulted"];
-      extra: Record<string, T["_zod"]["output"]>;
-    }
-  >;
-  /** Consider `z.strictObject({ ...A.shape })` instead. */
-  strict(): ZodInterface<
-    Shape,
-    {
-      optional: Params["optional"];
-      defaulted: Params["defaulted"];
-      extra: {};
-    }
-  >;
-
-  loose(): ZodInterface<
-    Shape,
-    {
-      optional: Params["optional"];
-      defaulted: Params["defaulted"];
-      extra: Record<string, unknown>;
-    }
-  >;
-
-  /**  Use `z.looseObject({ ...A.shape })` instead. */
-  strip(): ZodInterface<
-    Shape,
-    {
-      optional: Params["optional"];
-      defaulted: Params["defaulted"];
-      extra: {};
-    }
-  >;
-
-  extend<U extends ZodInterface>(int: U): MergeInterfaces<this, U>;
-  extend<U extends core.$ZodLooseShape>(
-    shape: U
-  ): MergeInterfaces<this, ZodInterface<U, util.InitInterfaceParams<U, {}>>>;
-
-  /** @deprecated Use `A.extend(B)` */
-  merge<U extends ZodInterface>(incoming: U): MergeInterfaces<this, U>;
-
-  pick<const M extends util.Exactly<util.Mask<string & keyof Shape>, M>>(
-    mask: M
-  ): ZodInterface<
-    util.Flatten<Pick<Shape, keyof Shape & keyof M>>,
-    {
-      optional: Extract<Params["optional"], keyof M>;
-      defaulted: Extract<Params["defaulted"], keyof M>;
-      extra: Params["extra"];
-    }
-  >;
-
-  omit<const M extends util.Exactly<util.Mask<string & keyof Shape>, M>>(
-    mask: M
-  ): ZodInterface<
-    util.Flatten<Omit<Shape, keyof M>>,
-    {
-      optional: Exclude<Params["optional"], keyof M>;
-      defaulted: Exclude<Params["defaulted"], keyof M>;
-      extra: Params["extra"];
-    }
-  >;
-
-  partial(): ZodInterfacePartial<this>;
-  partial<M extends util.Mask<string & keyof Shape>>(mask: M): ZodInterfacePartial<this, string & keyof M>;
-
-  required(): ZodInterfaceRequired<this, string & keyof Shape>;
-  required<M extends util.Mask<string & keyof Shape>>(mask: M): ZodInterfaceRequired<this, string & keyof M>;
-}
-export const ZodInterface: core.$constructor<ZodInterface> = /*@__PURE__*/ core.$constructor(
-  "ZodInterface",
-  (inst, def) => {
-    core.$ZodInterface.init(inst, def);
-    ZodType.init(inst, def);
-    // util.defineLazy(inst._zod, "shape", () => def.shape);
-
-    inst.keyof = () => _enum(Object.keys(inst._zod.def.shape));
-    inst.catchall = (catchall) => inst.clone({ ...inst._zod.def, catchall });
-    inst.loose = () => inst.clone({ ...inst._zod.def, catchall: unknown() });
-    inst.strict = () => inst.clone({ ...inst._zod.def, catchall: never() });
-    inst.strip = () => inst.clone({ ...inst._zod.def, catchall: undefined });
-    inst.extend = (incoming: any) => {
-      if (incoming instanceof core.$ZodInterface) return util.extendObjectLike(inst, incoming);
-      return util.extendObjectLike(inst, _interface(incoming));
-    };
-    inst.merge = (other) => util.mergeObjectLike(inst, other);
-    inst.pick = (mask) => util.pick(inst, mask) as any;
-    inst.omit = (mask) => util.omit(inst, mask);
-    inst.partial = (...args: any[]) => util.partialObjectLike(ZodOptional, inst, args[0]);
-    inst.required = (...args: any[]) => util.requiredObjectLike(ZodNonOptional, inst, args[0]);
-  }
-);
-
-function _interface<T extends core.$ZodLooseShape>(
-  shape: T,
-  params?: string | core.$ZodInterfaceParams,
-  Class: util.Constructor<ZodInterface> = ZodInterface
-): ZodInterface<util.CleanInterfaceShape<T>, util.InitInterfaceParams<T, {}>> {
-  const cleaned = util.cached(() => util.cleanInterfaceShape(shape));
-  const def: core.$ZodInterfaceDef = {
-    type: "interface",
-    get shape() {
-      // return cleaned.value.shape;
-      const _shape = cleaned.value.shape;
-      util.assignProp(this, "shape", _shape);
-      return _shape;
-    },
-    get optional() {
-      return cleaned.value.optional;
-    },
-    ...util.normalizeParams(params),
-  };
-  return new Class(def) as any;
-}
-export { _interface as interface };
+/**
+ *
+ * shape {a, "b?", "c"}
+ * mask: {a, b}
+ * result: { "a?", "b?", c }
+ *
+ */
+// type AddQ<T extends string> = T extends `${infer R}?` ? T : `${T}?`;
+// type ZodInterfacePartial<T extends ZodInterface, MaskKeys extends PropertyKey = keyof T["shape"]> = util.Identity<
+//   ZodInterface<
+//     // util.Extend<
+//     //   T["shape"],
+//     //   {
+//     //     [k in Keys]: ZodOptional<T["shape"][k]>;
+//     //   }
+//     // >,
+//     // {
+//     //   // remove mask keys
+//     //   [k in keyof T["shape"] as k extends T["_cleanToRaw"][string & keyof Mask] ? never : k]: T["shape"][k];
+//     // } & {
+//     //   [k in keyof Mask as `${k & string}?`]: ZodOptional<T["shape"][T["_cleanToRaw"][k & string]]>;
+//     // },
+//     {
+//       [k in keyof T["shape"] as util.CleanKey<k> extends MaskKeys ? `${util.CleanKey<k> & string}?` : k]: T["shape"][k];
+//     },
+//     T["_zod"]["extra"]
+//   >
+// >;
+
+// type ZodInterfaceRequired<T extends ZodInterface, Keys extends keyof T["shape"] = keyof T["shape"]> = ZodInterface<
+//   util.Extend<
+//     T["shape"],
+//     {
+//       [k in Keys]: ZodNonOptional<T["shape"][k]>;
+//     }
+//   >,
+//   {
+//     optional: never;
+//     defaulted: T["_zod"]["defaulted"];
+//     extra: T["_zod"]["extra"];
+//   }
+// >;
+
+// export type PartialInterfaceShape<
+//   Shape extends core.$ZodLooseShape,
+//   Keys extends PropertyKey = keyof Shape,
+// > = util.Identity<{
+//   [k in keyof Shape as util.CleanKey<k> extends Keys ? `${util.CleanKey<k> & string}?` : k]: Shape[k];
+// }>;
+// export type RequiredInterfaceShape<
+//   Shape extends core.$ZodLooseShape,
+//   Keys extends PropertyKey = keyof Shape,
+// > = util.Identity<
+//   {
+//     [k in keyof Shape as k extends Keys ? k : never]-?: ZodNonOptional<NonNullable<Shape[k]>>;
+//   } & {
+//     [k in keyof Shape as k extends Keys ? never : k]-?: NonNullable<Shape[k]>;
+//   }
+// >;
+// export type ExtendInterfaceShape<
+//   Shape extends core.$ZodLooseShape,
+//   Incoming extends core.$ZodLooseShape,
+// > = util.CleanKey<keyof Shape> & util.CleanKey<keyof Incoming> extends never
+//   ? Shape & Incoming
+//   : util.Identity<
+//       {
+//         [k in util.CleanKey<keyof Shape> as util.CleanKey<k> extends util.CleanKey<keyof Incoming>
+//           ? never
+//           : k]: Shape[k];
+//       } & {
+//         [k in keyof Incoming]: Incoming[k];
+//       }
+//     >;
+
+// export type MergeInterfaces<A extends ZodInterface, B extends core.$ZodLooseShape> = ZodInterface<
+//   util.Extend<A["shape"], B["shape"]>,
+//   A["_zod"]["outextra"],
+//   A["_zod"]["inextra"]
+// >;
+
+// type lkajdf = util.ToCleanMap<{
+//   a: ZodString;
+//   "b?": ZodString;
+//   "?c": ZodString;
+// }>;
+
+// type lkajdfdf = util.FromCleanMap<{
+//   a: ZodString;
+//   "b?": ZodString;
+//   "?c": ZodString;
+// }>;
+// export interface ZodInterface<
+//   // @ts-ignore cast variance
+//   out Shape extends core.$ZodLooseShape = core.$ZodLooseShape,
+//   OutExtra extends Record<string, unknown> = Record<string, unknown>,
+//   InExtra extends Record<string, unknown> = Record<string, unknown>,
+// > extends ZodType {
+//   _zod: core.$ZodInterfaceInternals<Shape, OutExtra, InExtra>;
+//   shape: Shape;
+//   // _rawToClean: util.ToCleanMap<Shape>;
+//   // _cleanToRaw: util.FromCleanMap<Shape>;
+
+//   keyof(): ZodEnum<util.ToEnum<util.InterfaceKeys<string & keyof Shape>>>;
+//   catchall<T extends core.$ZodType>(schema: T): ZodInterface<Shape, Record<string, T["_zod"]["output"]>>;
+//   strict(): ZodInterface<Shape, {}>;
+//   loose(): ZodInterface<Shape, Record<string, unknown>>;
+//   strip(): ZodInterface<Shape, {}>;
+
+//   /** This API is discouraged, as it can degrade `tsc` compiler performance in some cases. Instead, create a new object type using the `.shape` property.
+//    * ```
+//    * const myNewSchema = z.interface({ ...A.shape, newField: z.string() })
+//    * ``` */
+//   extend<U extends core.$ZodLooseShape>(
+//     shape: U
+//   ): ZodInterface<util.Extend<Shape, ProcessInterfaceShape<U>>, OutExtra, InExtra>;
+
+//   /** @deprecated Use `z.interface({ ...A.shape, ...B.shape })` */
+//   merge<U extends ZodInterface>(
+//     incoming: U
+//   ): ZodInterface<util.Extend<Shape, U["shape"]>, OutExtra & U["_zod"]["outextra"], InExtra & U["_zod"]["inextra"]>;
+
+//   pick<const M extends util.Exactly<util.Mask<keyof Shape>, M>>(
+//     mask: M
+//   ): ZodInterface<Pick<Shape, string & keyof M>, OutExtra, InExtra>;
+
+//   omit<const M extends util.Exactly<util.Mask<keyof Shape>, M>>(
+//     mask: M
+//   ): ZodInterface<Omit<Shape, string & keyof M>, OutExtra, InExtra>;
+
+//   partial(): ZodInterface<Partial<Shape>, OutExtra, InExtra>;
+//   partial<M extends util.Exactly<util.Mask<keyof Shape>, M>>(
+//     mask: M
+//   ): ZodInterface<util.MakePartial<Shape, string & keyof M>, OutExtra, InExtra>;
+
+//   required(): ZodInterface<RequiredInterfaceShape<Shape>, OutExtra, InExtra>;
+//   required<M extends util.Exactly<util.Mask<string & keyof Shape>, M>>(
+//     mask: M
+//   ): ZodInterface<RequiredInterfaceShape<Shape, keyof M>, OutExtra, InExtra>;
+// }
+// export const ZodInterface: core.$constructor<ZodInterface> = /*@__PURE__*/ core.$constructor(
+//   "ZodInterface",
+//   (inst, def) => {
+//     core.$ZodInterface.init(inst, def);
+//     ZodType.init(inst, def);
+
+//     const shape = {} as any;
+//     for (const key in inst._zod.def.shape) {
+//       const value = inst._zod.def.shape[key];
+//       if (value.optionality === "optional") {
+//         shape[key + "?"] = value;
+//       } else {
+//         shape[key] = value;
+//       }
+//     }
+//     inst.shape = shape;
+
+//     inst.keyof = () => _enum(Object.keys(inst._zod.def.shape));
+//     inst.catchall = (catchall) => inst.clone({ ...inst._zod.def, catchall });
+//     inst.loose = () => inst.clone({ ...inst._zod.def, catchall: unknown() });
+//     inst.strict = () => inst.clone({ ...inst._zod.def, catchall: never() });
+//     inst.strip = () => inst.clone({ ...inst._zod.def, catchall: undefined });
+//     inst.extend = (incoming: any) => {
+//       if (incoming instanceof core.$ZodInterface) return util.extendObjectLike(inst, incoming);
+//       return util.extendObjectLike(inst, _interface(incoming));
+//     };
+//     inst.merge = (other) => util.mergeObjectLike(inst, other);
+//     inst.pick = (mask) => util.pick(inst, mask) as any;
+//     inst.omit = (mask) => util.omit(inst, mask);
+//     inst.partial = (...args: any[]) => util.partialObjectLike(null, inst, args[0]);
+//     inst.required = (...args: any[]) => util.requiredObjectLike(ZodNonOptional, inst, args[0]);
+//   }
+// );
+
+// export type ProcessInterfaceShape<T extends core.$ZodLooseShape> = {
+//   [k in keyof T as k extends `${infer K}?` ? K : never]?: T[k];
+// } & {
+//   [k in keyof T as k extends `${string}?` ? never : k]: T[k];
+// };
+// function _interface<T extends core.$ZodLooseShape>(
+//   shape: T,
+//   params?: string | core.$ZodInterfaceParams,
+//   Class: util.Constructor<ZodInterface> = ZodInterface
+// ): ZodInterface<T, {}, {}> {
+//   const cleaned = util.cached(() => util.cleanInterfaceShape(shape));
+//   const def: core.$ZodInterfaceDef = {
+//     type: "interface",
+//     get shape() {
+//       // return cleaned.value.shape;
+//       const _shape = cleaned.value.shape;
+//       util.assignProp(this, "shape", _shape);
+//       return _shape;
+//     },
+//     // get shapeMeta() {
+//     //   return cleaned.value.shapeMeta;
+//     // },
+//     // get _rawShape() {
+//     //   // not cached!
+//     //   return cleaned.value.shape;
+//     // },
+//     // get optional() {
+//     //   return cleaned.value.optional;
+//     // },
+//     ...util.normalizeParams(params),
+//   };
+//   return new Class(def) as any;
+// }
+// export { _interface as interface };
 
 // strictInterface
 
-export function strictInterface<T extends core.$ZodLooseShape>(
-  shape: T,
-  params?: string | core.$ZodInterfaceParams
-): ZodInterface<util.CleanInterfaceShape<T>, util.InitInterfaceParams<T, {}>> {
-  const cleaned = util.cached(() => util.cleanInterfaceShape(shape));
-  const def: core.$ZodInterfaceDef = {
-    type: "interface",
-    get shape() {
-      // return cleaned.value.shape;
-      const _shape = cleaned.value.shape;
-      util.assignProp(this, "shape", _shape);
-      return _shape;
-    },
-    get optional() {
-      return cleaned.value.optional;
-    },
-    catchall: never(),
-    ...util.normalizeParams(params),
-  };
-  return new ZodInterface(def) as any;
-}
-
-// looseInterface
+// export function strictInterface<T extends core.$ZodLooseShape>(
+//   shape: T,
+//   params?: string | core.$ZodInterfaceParams
+// ): ZodInterface<T, {}> {
+//   const cleaned = util.cached(() => util.cleanInterfaceShape(shape));
+
+//   const def: core.$ZodInterfaceDef = {
+//     type: "interface",
+//     get shape() {
+//       // return cleaned.value.shape;
+
+//       const _shape = cleaned.value.shape;
+//       util.assignProp(this, "shape", _shape);
+//       return _shape;
+//     },
+//     // get shapeMeta() {
+//     //   return cleaned.value.shapeMeta;
+//     // },
+//     // get _rawShape() {
+//     //   // not cached!
+//     //   return cleaned.value.shape;
+//     // },
+//     // get optional() {
+//     //   return cleaned.value.optional;
+//     // },
+//     catchall: never(),
+//     ...util.normalizeParams(params),
+//   };
+//   return new ZodInterface(def) as any;
+// }
 
-export function looseInterface<T extends core.$ZodLooseShape>(
-  shape: T,
-  params?: string | core.$ZodInterfaceParams
-): ZodInterface<util.CleanInterfaceShape<T>, util.InitInterfaceParams<T, Record<string, unknown>>> {
-  const cleaned = util.cached(() => util.cleanInterfaceShape(shape));
-  const def: core.$ZodInterfaceDef = {
-    type: "interface",
-    get optional() {
-      return cleaned.value.optional;
-    },
-    get shape() {
-      // return cleaned.value.shape;
-      const _shape = cleaned.value.shape;
-      util.assignProp(this, "shape", _shape);
-      return _shape;
-    },
-    catchall: unknown(),
-    ...util.normalizeParams(params),
-  };
-  return new ZodInterface(def) as any;
-}
+// // looseInterface
+
+// export function looseInterface<T extends core.$ZodLooseShape>(
+//   shape: T,
+//   params?: string | core.$ZodInterfaceParams
+// ): ZodInterface<T, Record<string, unknown>> {
+//   const cleaned = util.cached(() => util.cleanInterfaceShape(shape));
+//   const def: core.$ZodInterfaceDef = {
+//     type: "interface",
+//     // get optional() {
+//     //   return cleaned.value.optional;
+//     // },
+//     get shape() {
+//       // return cleaned.value.shape;
+//       const _shape = cleaned.value.shape;
+//       util.assignProp(this, "shape", _shape);
+//       return _shape;
+//     },
+//     // get shapeMeta() {
+//     //   return cleaned.value.shapeMeta;
+//     // },
+
+//     // get _rawShape() {
+//     //   // not cached!
+//     //   return cleaned.value.shape;
+//     // },
+//     catchall: unknown(),
+//     ...util.normalizeParams(params),
+//   };
+//   return new ZodInterface(def) as any;
+// }
 
 // ZodObject
 export interface ZodObject<
   // @ts-ignore cast variance
-  out Shape extends core.$ZodShape = core.$ZodShape,
-  // @ts-ignore cast variance
-  Extra extends Record<string, unknown> = Record<string, unknown>,
+  out Shape extends core.$ZodShape = core.$ZodLooseShape,
+  OutExtra extends Record<string, unknown> = Record<string, unknown>,
+  InExtra extends Record<string, unknown> = Record<string, unknown>,
 > extends ZodType {
-  _zod: core.$ZodObjectInternals<Shape, Extra>;
-
+  _zod: core.$ZodObjectInternals<Shape, OutExtra, InExtra>;
   shape: Shape;
 
   keyof(): ZodEnum<util.ToEnum<keyof Shape & string>>;
@@ -1275,33 +1325,52 @@ export interface ZodObject<
   /** This is the default behavior. This method call is likely unnecessary. */
   strip(): ZodObject<Shape, {}>;
 
-  extend<const U extends ZodObject>(schema: U): ZodObject<util.Extend<Shape, U["_zod"]["def"]["shape"]>, Extra>;
-  extend<U extends core.$ZodShape>(
+  extend<U extends core.$ZodLooseShape>(
     shape: U
   ): ZodObject<
     util.Extend<Shape, U>,
-    Extra // & B['_zod']["extra"]
+    OutExtra,
+    InExtra // & B['_zod']["extra"]
   >;
 
-  // merge
-  /** @deprecated Use `A.extend(B.shape)` */
-  merge<U extends ZodObject<any, any>>(
+  /**
+   * @deprecated Use destructuring to merge the shapes:
+   *
+   * ```ts
+   * z.object({
+   *    ...A.shape,
+   *    ...B.shape
+   * });
+   * ```
+   */
+  merge<U extends ZodObject>(
     other: U
-  ): ZodObject<util.Flatten<util.Extend<Shape, U["_zod"]["def"]["shape"]>>, Extra>;
+  ): ZodObject<util.Extend<Shape, U["shape"]>, U["_zod"]["outextra"], U["_zod"]["inextra"]>;
+  /**
+   * @deprecated Use destructuring to merge the shapes:
+   *
+   * ```ts
+   * z.object({
+   *    ...A.shape,
+   *    ...B.shape
+   * });
+   * ```
+   */
 
   pick<M extends util.Exactly<util.Mask<string & keyof Shape>, M>>(
     mask: M
-  ): ZodObject<util.Flatten<Pick<Shape, Extract<keyof Shape, keyof M>>>, Extra>;
+  ): ZodObject<util.Flatten<Pick<Shape, Extract<keyof Shape, keyof M>>>, OutExtra, InExtra>;
 
   omit<M extends util.Exactly<util.Mask<string & keyof Shape>, M>>(
     mask: M
-  ): ZodObject<util.Flatten<Omit<Shape, Extract<keyof Shape, keyof M>>>, Extra>;
+  ): ZodObject<util.Flatten<Omit<Shape, Extract<keyof Shape, keyof M>>>, OutExtra, InExtra>;
 
   partial(): ZodObject<
     {
       [k in keyof Shape]: ZodOptional<Shape[k]>;
     },
-    Extra
+    OutExtra,
+    InExtra
   >;
   partial<M extends util.Exactly<util.Mask<string & keyof Shape>, M>>(
     mask: M
@@ -1309,7 +1378,8 @@ export interface ZodObject<
     {
       [k in keyof Shape]: k extends keyof M ? ZodOptional<Shape[k]> : Shape[k];
     },
-    Extra
+    OutExtra,
+    InExtra
   >;
 
   // required
@@ -1317,7 +1387,8 @@ export interface ZodObject<
     {
       [k in keyof Shape]: ZodNonOptional<Shape[k]>;
     },
-    Extra
+    OutExtra,
+    InExtra
   >;
   required<M extends util.Exactly<util.Mask<string & keyof Shape>, M>>(
     mask: M
@@ -1325,14 +1396,18 @@ export interface ZodObject<
     {
       [k in keyof Shape]: k extends keyof M ? ZodNonOptional<Shape[k]> : Shape[k];
     },
-    Extra
+    OutExtra,
+    InExtra
   >;
 }
+
 export const ZodObject: core.$constructor<ZodObject> = /*@__PURE__*/ core.$constructor("ZodObject", (inst, def) => {
   core.$ZodObject.init(inst, def);
   ZodType.init(inst, def);
 
-  inst.shape = def.shape;
+  util.defineLazy(inst, "shape", () => {
+    return Object.fromEntries(Object.entries(inst._zod.def.shape));
+  });
   inst.keyof = () => _enum(Object.keys(inst._zod.def.shape)) as any;
   inst.catchall = (catchall) => inst.clone({ ...inst._zod.def, catchall });
   inst.passthrough = () => inst.clone({ ...inst._zod.def, catchall: unknown() });
@@ -1351,16 +1426,24 @@ export const ZodObject: core.$constructor<ZodObject> = /*@__PURE__*/ core.$const
   inst.partial = (...args: any[]) => util.partialObjectLike(ZodOptional, inst, args[0] as object);
   inst.required = (...args: any[]) => util.requiredObjectLike(ZodNonOptional, inst, args[0] as object);
 });
-export function object<T extends core.$ZodShape = Record<never, core.$ZodType>>(
+
+export function object<T extends core.$ZodLooseShape = Record<never, core.$ZodType>>(
   shape?: T,
   params?: string | core.$ZodObjectLikeParams
-): ZodObject<T, {}> {
+): ZodObject<util.Writeable<T> & {}, {}, {}> {
   const def: core.$ZodObjectDef = {
     type: "object",
-    shape: shape ?? {},
-    get optional() {
-      return util.optionalObjectKeys(shape ?? {});
+    // shape: shape ?? {},
+    get shape() {
+      util.assignProp(this, "shape", { ...shape });
+      return this.shape;
     },
+    // get shape() {
+    //   return util.objectShapeMeta(shape ?? {});
+    // },
+    // get optional() {
+    //   return util.optionalObjectKeys(shape ?? {});
+    // },
     ...util.normalizeParams(params),
   };
   return new ZodObject(def) as any;
@@ -1368,16 +1451,20 @@ export function object<T extends core.$ZodShape = Record<never, core.$ZodType>>(
 
 // strictObject
 
-export function strictObject<T extends core.$ZodShape>(
+export function strictObject<T extends core.$ZodLooseShape>(
   shape: T,
   params?: string | core.$ZodObjectParams
-): ZodObject<T, {}> {
+): ZodObject<T, {}, {}> {
   return new ZodObject({
     type: "object",
-    shape: shape as core.$ZodShape,
-    get optional() {
-      return util.optionalObjectKeys(shape);
+    // shape: shape as core.$ZodShape,
+    get shape() {
+      util.assignProp(this, "shape", { ...shape });
+      return this.shape;
     },
+    // get optional() {
+    //   return util.optionalObjectKeys(shape);
+    // },
     catchall: never(),
     ...util.normalizeParams(params),
   }) as any;
@@ -1385,214 +1472,221 @@ export function strictObject<T extends core.$ZodShape>(
 
 // looseObject
 
-export function looseObject<T extends core.$ZodShape>(
+export function looseObject<T extends core.$ZodLooseShape>(
   shape: T,
   params?: string | core.$ZodObjectParams
-): ZodObject<T, { [k: string]: unknown }> {
+): ZodObject<T, { [k: string]: unknown }, { [k: string]: unknown }> {
   return new ZodObject({
     type: "object",
-    shape: shape as core.$ZodShape,
-    get optional() {
-      return util.optionalObjectKeys(shape);
+    // shape: shape as core.$ZodShape,
+    get shape() {
+      util.assignProp(this, "shape", { ...shape });
+      return this.shape;
     },
+    // get optional() {
+    //   return util.optionalObjectKeys(shape);
+    // },
     catchall: unknown(),
     ...util.normalizeParams(params),
   }) as any;
 }
 
 // object methods
-export function extend<T extends ZodInterface, U extends ZodInterface>(
-  a: T,
-  b: U
-): ZodInterface<util.Extend<T["_zod"]["def"]["shape"], U["_zod"]["def"]["shape"]>, util.MergeInterfaceParams<T, U>>;
-export function extend<T extends ZodObject, U extends ZodObject>(
-  a: T,
-  b: U
-): ZodObject<
-  util.Extend<T["_zod"]["def"]["shape"], U["_zod"]["def"]["shape"]>,
-  U["_zod"]["extra"] & T["_zod"]["extra"]
->;
-export function extend<T extends ZodObjectLike, U extends core.$ZodLooseShape>(
-  schema: T,
-  shape: U
-): T extends ZodInterface<infer TShape, infer TParams>
-  ? ZodInterface<util.ExtendInterfaceShape<TShape, U>, util.ExtendInterfaceParams<ZodInterface<TShape, TParams>, U>>
-  : ZodObject<util.Extend<T["_zod"]["def"]["shape"], U>, T["_zod"]["extra"]>;
-export function extend(schema: ZodObjectLike, shape: core.$ZodShape): ZodObjectLike {
-  if (shape instanceof core.$ZodType) return util.mergeObjectLike(schema, shape as any);
-  if (schema instanceof ZodInterface) {
-    return util.mergeObjectLike(schema, _interface(shape));
-  }
-  if (schema instanceof ZodObject) return util.mergeObjectLike(schema, object(shape));
-  return util.extend(schema, shape);
-}
-
-export function merge<T extends ZodObjectLike, U extends core.$ZodLooseShape>(
-  schema: T,
-  shape: U
-): T["_zod"]["def"]["type"] extends "interface"
-  ? // T extends ZodInterface
-    ZodInterface<
-      util.Extend<T["_zod"]["def"]["shape"], U["_zod"]["def"]["shape"]>,
-      {
-        extra: T["_zod"]["extra"] & U["_zod"]["extra"];
-        optional: Exclude<T["_zod"]["optional"], keyof U["_zod"]["def"]["shape"]> | U["_zod"]["optional"];
-        defaulted: Exclude<T["_zod"]["defaulted"], keyof U["_zod"]["def"]["shape"]> | U["_zod"]["defaulted"];
-      }
-    >
-  : ZodObject<util.Extend<T["_zod"]["def"]["shape"], U>, T["_zod"]["extra"]>;
-export function merge(a: ZodObjectLike, b: ZodObjectLike): ZodObjectLike {
-  return util.mergeObjectLike(a, b);
-}
+// export function extend<T extends ZodInterface, U extends ZodInterface>(
+//   a: T,
+//   b: U
+// ): ZodInterface<util.Extend<T["_zod"]["def"]["shape"], U["_zod"]["def"]["shape"]>, util.MergeInterfaceParams<T, U>>;
+// export function extend<T extends ZodObject, U extends ZodObject>(
+//   a: T,
+//   b: U
+// ): ZodObject<
+//   util.Extend<T["_zod"]["def"]["shape"], U["_zod"]["def"]["shape"]>,
+//   U["_zod"]["extra"] & T["_zod"]["extra"]
+// >;
+// export function extend<T extends ZodObjectLike, U extends core.$ZodLooseShape>(
+//   schema: T,
+//   shape: U
+// ): T extends ZodInterface<infer TShape, infer TExtra>
+//   ? ZodInterface<util.ExtendInterfaceShape<TShape, U>, util.ExtendInterfaceParams<ZodInterface<TShape, TExtra>, U>>
+//   : ZodObject<util.Extend<T["_zod"]["def"]["shape"], U>, T["_zod"]["extra"]>;
+// export function extend(schema: ZodObjectLike, shape: core.$ZodShape): ZodObjectLike {
+//   if (shape instanceof core.$ZodType) return util.mergeObjectLike(schema, shape as any);
+//   if (schema instanceof ZodInterface) {
+//     return util.mergeObjectLike(schema, _interface(shape));
+//   }
+//   if (schema instanceof ZodObject) return util.mergeObjectLike(schema, object(shape));
+//   return util.extend(schema, shape);
+// }
+
+// export function merge<T extends ZodObjectLike, U extends core.$ZodLooseShape>(
+//   schema: T,
+//   shape: U
+// ): T["_zod"]["def"]["type"] extends "interface"
+//   ? // T extends ZodInterface
+//     ZodInterface<
+//       util.Extend<T["_zod"]["def"]["shape"], U["_zod"]["def"]["shape"]>,
+//       {
+//         extra: T["_zod"]["extra"] & U["_zod"]["extra"];
+//         optional: Exclude<T["_zod"]["optional"], keyof U["_zod"]["def"]["shape"]> | U["_zod"]["optional"];
+//         defaulted: Exclude<T["_zod"]["defaulted"], keyof U["_zod"]["def"]["shape"]> | U["_zod"]["defaulted"];
+//       }
+//     >
+//   : ZodObject<util.Extend<T["_zod"]["def"]["shape"], U>, T["_zod"]["extra"]>;
+// export function merge(a: ZodObjectLike, b: ZodObjectLike): ZodObjectLike {
+//   return util.mergeObjectLike(a, b);
+// }
 
 // .pick
-export function pick<T extends ZodObjectLike, M extends util.Exactly<util.Mask<keyof T["_zod"]["def"]["shape"]>, M>>(
-  schema: T,
-  mask: M
-): T["_zod"]["def"]["type"] extends "interface"
-  ? ZodInterface<
-      util.Flatten<Pick<T["_zod"]["def"]["shape"], keyof T["_zod"]["def"]["shape"] & keyof M>>,
-      {
-        optional: Extract<T["_zod"]["optional"], keyof M>;
-        defaulted: Extract<T["_zod"]["defaulted"], keyof M>;
-        extra: T["_zod"]["extra"];
-      }
-    >
-  : ZodObject<
-      util.Flatten<Pick<T["_zod"]["def"]["shape"], keyof T["_zod"]["def"]["shape"] & keyof M>>,
-      T["_zod"]["extra"]
-    >;
-export function pick(schema: ZodObjectLike, mask: object) {
-  // const picked = util.pick(schema, mask);
-  return util.pick(schema, mask);
-}
-
-// .omit
-export function omit<
-  T extends ZodObjectLike,
-  const M extends util.Exactly<util.Mask<keyof T["_zod"]["def"]["shape"]>, M>,
->(
-  schema: T,
-  mask: M
-): T["_zod"]["def"]["type"] extends "interface"
-  ? ZodInterface<
-      util.Flatten<Omit<T["_zod"]["def"]["shape"], keyof M>>,
-      {
-        optional: Exclude<T["_zod"]["optional"], keyof M>;
-        defaulted: Exclude<T["_zod"]["defaulted"], keyof M>;
-        extra: T["_zod"]["extra"];
-      }
-    >
-  : ZodObject<util.Flatten<Omit<T["_zod"]["def"]["shape"], keyof M>>, T["_zod"]["extra"]>;
-
-export function omit(schema: ZodObjectLike, mask: object) {
-  return util.omit(schema, mask);
-}
-
-export function partial<T extends ZodObjectLike>(
-  schema: T
-): T["_zod"]["def"]["type"] extends "interface"
-  ? ZodInterface<
-      // T['_zod']["shape"],
-      {
-        [k in keyof T["_zod"]["def"]["shape"]]: ZodOptional<T["_zod"]["def"]["shape"][k]>;
-      },
-      {
-        optional: string & keyof T["_zod"]["def"]["shape"];
-        defaulted: never;
-        extra: T["_zod"]["extra"];
-      }
-    >
-  : ZodObject<
-      {
-        [k in keyof T["_zod"]["def"]["shape"]]: ZodOptional<T["_zod"]["def"]["shape"][k]>;
-      },
-      T["_zod"]["extra"]
-    >;
-export function partial<T extends ZodObjectLike, M extends util.Exactly<util.Mask<keyof T["_zod"]["def"]["shape"]>, M>>(
-  schema: T,
-  mask: M
-): T["_zod"]["def"]["type"] extends "interface"
-  ? ZodInterface<
-      util.Extend<
-        T["_zod"]["def"]["shape"],
-        {
-          [k in keyof M & keyof T["_zod"]["def"]["shape"]]: ZodOptional<T["_zod"]["def"]["shape"][k]>;
-        }
-      >,
-      {
-        optional: string & (T["_zod"]["optional"] | keyof M);
-        defaulted: T["_zod"]["defaulted"];
-        extra: T["_zod"]["extra"];
-      }
-    >
-  : ZodObject<
-      {
-        [k in keyof T["_zod"]["def"]["shape"]]: k extends keyof M
-          ? ZodOptional<T["_zod"]["def"]["shape"][k]>
-          : T["_zod"]["def"]["shape"][k];
-      },
-      T["_zod"]["extra"]
-    >;
-
-export function partial(schema: ZodObjectLike, mask?: object): ZodObjectLike {
-  return util.partialObjectLike(ZodOptional, schema, mask);
-}
-
-// .required
-export function required<T extends { _subtype: "object" } & ZodObject>(
-  schema: T
-): ZodObject<{
-  [k in keyof T["_zod"]["def"]["shape"]]: ZodNonOptional<T["_zod"]["def"]["shape"][k]>;
-}>;
-export function required<
-  T extends { _subtype: "object" } & ZodObject,
-  M extends util.Exactly<util.Mask<keyof T["_zod"]["def"]["shape"]>, M>,
->(
-  schema: T,
-  mask: M
-): ZodObject<
-  util.Extend<
-    T["_zod"]["def"]["shape"],
-    {
-      [k in keyof M & keyof T["_zod"]["def"]["shape"]]: ZodNonOptional<T["_zod"]["def"]["shape"][k]>;
-    }
-  >
->;
-export function required<T extends { _subtype: "interface" } & ZodInterface>(
-  schema: T
-): ZodInterface<
-  {
-    [k in keyof T["_zod"]["def"]["shape"]]: ZodNonOptional<T["_zod"]["def"]["shape"][k]>;
-  },
-  {
-    optional: never;
-    defaulted: T["_zod"]["defaulted"];
-    extra: T["_zod"]["extra"];
-  }
->;
-export function required<
-  T extends { _subtype: "interface" } & ZodInterface,
-  M extends util.Mask<keyof T["_zod"]["output"]>,
->(
-  schema: T,
-  mask: M
-): ZodInterface<
-  util.Extend<
-    T["_zod"]["def"]["shape"],
-    {
-      [k in keyof M & keyof T["_zod"]["def"]["shape"]]: ZodNonOptional<T["_zod"]["def"]["shape"][k]>;
-    }
-  >,
-  {
-    optional: Exclude<T["_zod"]["optional"], keyof M>;
-    defaulted: T["_zod"]["defaulted"];
-    extra: T["_zod"]["extra"];
-  }
->;
-export function required(schema: ZodObjectLike, mask?: object): ZodObjectLike {
-  return util.requiredObjectLike(ZodNonOptional, schema, mask);
-}
+// export function pick<T extends ZodObjectLike, M extends util.Exactly<util.Mask<keyof T["_zod"]["def"]["shape"]>, M>>(
+//   schema: T,
+//   mask: M
+// ): T["_zod"]["def"]["type"] extends "interface"
+//   ? ZodInterface<
+//       util.Flatten<Pick<T["_zod"]["def"]["shape"], keyof T["_zod"]["def"]["shape"] & keyof M>>,
+//       {
+//         optional: Extract<T["_zod"]["optional"], keyof M>;
+//         defaulted: Extract<T["_zod"]["defaulted"], keyof M>;
+//         extra: T["_zod"]["extra"];
+//       }
+//     >
+//   : ZodObject<
+//       util.Flatten<Pick<T["_zod"]["def"]["shape"], keyof T["_zod"]["def"]["shape"] & keyof M>>,
+//       T["_zod"]["extra"]
+//     >;
+// export function pick(schema: ZodObjectLike, mask: object) {
+//   // const picked = util.pick(schema, mask);
+//   return util.pick(schema, mask);
+// }
+
+// // .omit
+// export function omit<
+//   T extends ZodObjectLike,
+//   const M extends util.Exactly<util.Mask<keyof T["_zod"]["def"]["shape"]>, M>,
+// >(
+//   schema: T,
+//   mask: M
+// ): T["_zod"]["def"]["type"] extends "interface"
+//   ? ZodInterface<
+//       util.Flatten<Omit<T["_zod"]["def"]["shape"], keyof M>>,
+//       {
+//         optional: Exclude<T["_zod"]["optional"], keyof M>;
+//         defaulted: Exclude<T["_zod"]["defaulted"], keyof M>;
+//         extra: T["_zod"]["extra"];
+//       }
+//     >
+//   : ZodObject<util.Flatten<Omit<T["_zod"]["def"]["shape"], keyof M>>, T["_zod"]["extra"]>;
+
+// export function omit(schema: ZodObjectLike, mask: object) {
+//   return util.omit(schema, mask);
+// }
+export function partial<T>(shape: T): Partial<T> {
+  return shape;
+}
+
+// export function partial<T extends ZodObjectLike>(
+//   schema: T
+// ): T["_zod"]["def"]["type"] extends "interface"
+//   ? ZodInterface<
+//       // T['_zod']["shape"],
+//       {
+//         [k in keyof T["_zod"]["def"]["shape"]]: ZodOptional<T["_zod"]["def"]["shape"][k]>;
+//       },
+//       {
+//         optional: string & keyof T["_zod"]["def"]["shape"];
+//         defaulted: never;
+//         extra: T["_zod"]["extra"];
+//       }
+//     >
+//   : ZodObject<
+//       {
+//         [k in keyof T["_zod"]["def"]["shape"]]: ZodOptional<T["_zod"]["def"]["shape"][k]>;
+//       },
+//       T["_zod"]["extra"]
+//     >;
+// export function partial<T extends ZodObjectLike, M extends util.Exactly<util.Mask<keyof T["_zod"]["def"]["shape"]>, M>>(
+//   schema: T,
+//   mask: M
+// ): T["_zod"]["def"]["type"] extends "interface"
+//   ? ZodInterface<
+//       util.Extend<
+//         T["_zod"]["def"]["shape"],
+//         {
+//           [k in keyof M & keyof T["_zod"]["def"]["shape"]]: ZodOptional<T["_zod"]["def"]["shape"][k]>;
+//         }
+//       >,
+//       {
+//         optional: string & (T["_zod"]["optional"] | keyof M);
+//         defaulted: T["_zod"]["defaulted"];
+//         extra: T["_zod"]["extra"];
+//       }
+//     >
+//   : ZodObject<
+//       {
+//         [k in keyof T["_zod"]["def"]["shape"]]: k extends keyof M
+//           ? ZodOptional<T["_zod"]["def"]["shape"][k]>
+//           : T["_zod"]["def"]["shape"][k];
+//       },
+//       T["_zod"]["extra"]
+//     >;
+
+// export function partial(schema: ZodObjectLike, mask?: object): ZodObjectLike {
+//   return util.partialObjectLike(ZodOptional, schema, mask);
+// }
+
+// // .required
+// export function required<T extends { _subtype: "object" } & ZodObject>(
+//   schema: T
+// ): ZodObject<{
+//   [k in keyof T["_zod"]["def"]["shape"]]: ZodNonOptional<T["_zod"]["def"]["shape"][k]>;
+// }>;
+// export function required<
+//   T extends { _subtype: "object" } & ZodObject,
+//   M extends util.Exactly<util.Mask<keyof T["_zod"]["def"]["shape"]>, M>,
+// >(
+//   schema: T,
+//   mask: M
+// ): ZodObject<
+//   util.Extend<
+//     T["_zod"]["def"]["shape"],
+//     {
+//       [k in keyof M & keyof T["_zod"]["def"]["shape"]]: ZodNonOptional<T["_zod"]["def"]["shape"][k]>;
+//     }
+//   >
+// >;
+// export function required<T extends { _subtype: "interface" } & ZodInterface>(
+//   schema: T
+// ): ZodInterface<
+//   {
+//     [k in keyof T["_zod"]["def"]["shape"]]: ZodNonOptional<T["_zod"]["def"]["shape"][k]>;
+//   },
+//   {
+//     optional: never;
+//     defaulted: T["_zod"]["defaulted"];
+//     extra: T["_zod"]["extra"];
+//   }
+// >;
+// export function required<
+//   T extends { _subtype: "interface" } & ZodInterface,
+//   M extends util.Mask<keyof T["_zod"]["output"]>,
+// >(
+//   schema: T,
+//   mask: M
+// ): ZodInterface<
+//   util.Extend<
+//     T["_zod"]["def"]["shape"],
+//     {
+//       [k in keyof M & keyof T["_zod"]["def"]["shape"]]: ZodNonOptional<T["_zod"]["def"]["shape"][k]>;
+//     }
+//   >,
+//   {
+//     optional: Exclude<T["_zod"]["optional"], keyof M>;
+//     defaulted: T["_zod"]["defaulted"];
+//     extra: T["_zod"]["extra"];
+//   }
+// >;
+// export function required(schema: ZodObjectLike, mask?: object): ZodObjectLike {
+//   return util.requiredObjectLike(ZodNonOptional, schema, mask);
+// }
 
 // ZodUnion
 export interface ZodUnion<T extends readonly core.$ZodType[] = readonly core.$ZodType[]> extends ZodType {
diff --git a/play.ts b/play.ts
index 55bbac99..bec05241 100644
--- a/play.ts
+++ b/play.ts
@@ -1,12 +1,16 @@
 import * as z from "zod";
 
-z;
-
-const frozenLetters = Object.freeze(["a", "b"]);
-const lettersAsConst = ["a", "b"] as const;
-
-const frozenLettersParser = z.enum(frozenLetters);
-const lettersAsConstParser = z.enum(lettersAsConst);
-
-console.log(frozenLettersParser.safeParse("a"));
-console.log(lettersAsConstParser.safeParse("a"));
+const Z = z.record(z.templateLiteral(["zod", z.string()]), z.number()).and(
+  z.object({
+    root: z.array(z.union([z.string(), z.number()])),
+    nested: z.object({
+      a: z.literal(true),
+    }),
+    inlined: z
+      .object({
+        b: z.literal(false),
+      })
+      .readonly()
+      .optional(),
+  })
+);
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index c43b2205..99fc1aa5 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -237,8 +237,8 @@ importers:
         specifier: workspace:*
         version: link:../mini
       arktype:
-        specifier: 2.0.0-rc.33
-        version: 2.0.0-rc.33
+        specifier: ^2.0.0
+        version: 2.1.19
       execa:
         specifier: ^9.5.2
         version: 9.5.2
@@ -258,8 +258,8 @@ importers:
         specifier: npm:zod@3.24.3
         version: zod@3.24.3
       zod4:
-        specifier: npm:zod@4.0.0-beta.20250415T232143
-        version: zod@4.0.0-beta.20250415T232143
+        specifier: npm:zod@4.0.0-beta.20250420T053007
+        version: zod@4.0.0-beta.20250420T053007
 
   packages/zod:
     dependencies:
@@ -285,15 +285,9 @@ packages:
     resolution: {integrity: sha512-Izvir8iIoU+X4SKtDAa5kpb+9cpifclzsbA8x/AZY0k0gIfXYQ1fa1B6Epfe6vNA2YfDX8VtrZFgvnXB6aPEoQ==}
     engines: {node: '>=18'}
 
-  '@ark/schema@0.33.0':
-    resolution: {integrity: sha512-GPjzbiydOL5gd9UFZMUQr5JBqT9YTX2dPT+u18aNswlGOgQE01y9B6kiwK/JyoaSwEJSDyxAPABsVRL7gG9KSQ==}
-
   '@ark/schema@0.45.9':
     resolution: {integrity: sha512-rG0v/JI0sibn/0wERAHTYVLCtEqoMP2IIlxnb+S5DrEjCI5wpubbZSWMDW50tZ8tV6FANu6zzHDeeKbp6lsZdg==}
 
-  '@ark/util@0.33.0':
-    resolution: {integrity: sha512-zzYQiRHLPwK15T5CM6SgQXTycKNpAvA2qwdlMbK5vFbLzy3P87VNKA8NiezBIXm+jsov3lEtMKE6kLtbZQDUbg==}
-
   '@ark/util@0.45.9':
     resolution: {integrity: sha512-0WYNAb8aRGp7dNt6xIvIrRzL7V1XL3u3PK2vcklhtTrdaP235DjC9qJhzidrxtWr68mA5ySSjUrgrXk622bKkw==}
 
@@ -2447,8 +2441,8 @@ packages:
   '@zag-js/types@1.8.2':
     resolution: {integrity: sha512-J+94HhFAPOBchNdGcmvqjB8nbQFgKHcqGoPl5vNTKlcoibN0yFjn4XFZoQU6uCf8sPhNg6NUNTkluR5YjybyJA==}
 
-  '@zod/core@0.5.1':
-    resolution: {integrity: sha512-Iqa3r1weIYaG1pjR+vNhfmaQ+5YtdQEp839R7bil0CC30cwiExXuBI5AAEjZMMS2CzGcBlAWca+0+vxzUmdJ6Q==}
+  '@zod/core@0.8.1':
+    resolution: {integrity: sha512-djj8hPhxIHcG8ptxITaw/Bout5HJZ9NyRbKr95Eilqwt9R0kvITwUQGDU+n+MVdsBIka5KwztmZSLti22F+P0A==}
 
   '@zxing/text-encoding@0.9.0':
     resolution: {integrity: sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA==}
@@ -2551,9 +2545,6 @@ packages:
     resolution: {integrity: sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==}
     engines: {node: '>=10'}
 
-  arktype@2.0.0-rc.33:
-    resolution: {integrity: sha512-ndtDXtunbff0o1urOOXq/eHGuUqIlp5MZ99lWON3MS0LZzF7/WFf+SwOCSomoPj9BptMLMyLS9cIYVNndD5QVQ==}
-
   arktype@2.1.19:
     resolution: {integrity: sha512-notORSuTSpfLV7rq0kYC4mTgIVlVR0xQuvtFxOaE9aKiXyON/kgoIBwZZcKeSSb4BebNcfJoGlxJicAUl/HMdw==}
 
@@ -2897,6 +2888,10 @@ packages:
     resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==}
     engines: {node: '>=8'}
 
+  detect-libc@2.0.4:
+    resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==}
+    engines: {node: '>=8'}
+
   detect-node-es@1.1.0:
     resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==}
 
@@ -5265,8 +5260,8 @@ packages:
   zod@3.24.3:
     resolution: {integrity: sha512-HhY1oqzWCQWuUqvBFnsyrtZRhyPeR7SUGv+C4+MsisMuVfSPx8HpwWqH8tRahSlt6M3PiFAcoeFhZAqIXTxoSg==}
 
-  zod@4.0.0-beta.20250415T232143:
-    resolution: {integrity: sha512-qy5jcyX/4Vt003S9II2NxTeAU31CQ71wJxk54stbrU+dhF+RcZL6xMwj8vGBbRVJi26pjCbTe2BldpK75nzlDw==}
+  zod@4.0.0-beta.20250420T053007:
+    resolution: {integrity: sha512-5pp8Q0PNDaNcUptGiBE9akyioJh3RJpagIxrLtAVMR9IxwcSZiOsJD/1/98CyhItdTlI2H91MfhhLzRlU+fifA==}
 
   zwitch@2.0.4:
     resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==}
@@ -5298,16 +5293,10 @@ snapshots:
       typescript: 5.6.1-rc
       validate-npm-package-name: 5.0.1
 
-  '@ark/schema@0.33.0':
-    dependencies:
-      '@ark/util': 0.33.0
-
   '@ark/schema@0.45.9':
     dependencies:
       '@ark/util': 0.45.9
 
-  '@ark/util@0.33.0': {}
-
   '@ark/util@0.45.9': {}
 
   '@babel/runtime@7.27.0':
@@ -7250,7 +7239,7 @@ snapshots:
     dependencies:
       csstype: 3.1.3
 
-  '@zod/core@0.5.1': {}
+  '@zod/core@0.8.1': {}
 
   '@zxing/text-encoding@0.9.0':
     optional: true
@@ -7337,11 +7326,6 @@ snapshots:
     dependencies:
       tslib: 2.8.1
 
-  arktype@2.0.0-rc.33:
-    dependencies:
-      '@ark/schema': 0.33.0
-      '@ark/util': 0.33.0
-
   arktype@2.1.19:
     dependencies:
       '@ark/schema': 0.45.9
@@ -7690,6 +7674,9 @@ snapshots:
 
   detect-libc@2.0.3: {}
 
+  detect-libc@2.0.4:
+    optional: true
+
   detect-node-es@1.1.0: {}
 
   devlop@1.1.0:
@@ -8612,7 +8599,7 @@ snapshots:
 
   lightningcss@1.29.3:
     dependencies:
-      detect-libc: 2.0.3
+      detect-libc: 2.0.4
     optionalDependencies:
       lightningcss-darwin-arm64: 1.29.3
       lightningcss-darwin-x64: 1.29.3
@@ -10691,8 +10678,8 @@ snapshots:
 
   zod@3.24.3: {}
 
-  zod@4.0.0-beta.20250415T232143:
+  zod@4.0.0-beta.20250420T053007:
     dependencies:
-      '@zod/core': 0.5.1
+      '@zod/core': 0.8.1
 
   zwitch@2.0.4: {}


Test patch:
diff --git a/packages/mini/tests/interface.test.ts b/packages/mini/tests/interface.test.ts
deleted file mode 100644
index fa00afc0..00000000
--- a/packages/mini/tests/interface.test.ts
+++ /dev/null
@@ -1,341 +0,0 @@
-import * as z from "@zod/mini";
-
-import { expect, expectTypeOf, test } from "vitest";
-
-test("z.interface", () => {
-  const a = z.interface({
-    name: z.string(),
-    age: z.number(),
-  });
-  expect(z.parse(a, { name: "john", age: 30 })).toEqual({
-    name: "john",
-    age: 30,
-  });
-  expect(() => z.parse(a, { name: "john", age: "30" })).toThrow();
-  expect(() => z.parse(a, "hello")).toThrow();
-});
-
-test("optionals", () => {
-  const a = z.interface({
-    a: z.string(),
-    "b?": z.string(),
-    "?c": z._default(z.string(), "c"),
-    d: z._default(z.string(), "d"),
-    e: z.optional(z.string()),
-    "?f": z.optional(z.string()),
-  });
-
-  interface a_in {
-    a: string;
-    b?: string;
-    c?: string;
-    d: string | undefined;
-    e: string | undefined;
-    f?: string | undefined;
-  }
-  interface a_out {
-    a: string;
-    b?: string;
-    c: string;
-    d: string;
-    e: string | undefined;
-    f: string | undefined;
-  }
-
-  expectTypeOf<typeof a._zod.output>().toEqualTypeOf<a_out>();
-  expectTypeOf<typeof a._zod.input>().toEqualTypeOf<a_in>();
-
-  // check parsing behavior
-  // b is optional in input and output
-  // c is optional in input but will always show up in output
-  // d is required in input & output but will be overwritten if `undefined`
-  // e is required in input & output but can be `undefined`
-  // f is optional in input but will always show up in output
-  expect(z.parse(a, { a: "a", b: "b", c: "c", d: "d", e: "e", f: "f" })).toEqual({
-    a: "a",
-    b: "b",
-    c: "c",
-    d: "d",
-    e: "e",
-    f: "f",
-  });
-
-  // omit b, c, and f to test optionality
-  expect(z.parse(a, { a: "a", d: "d", e: "e" })).toEqual({
-    a: "a",
-    c: "c", // default
-    d: "d",
-    e: "e",
-    f: undefined,
-  });
-
-  // test default values for d and f
-  expect(z.parse(a, { a: "a", d: undefined, e: "e", f: undefined })).toEqual({
-    a: "a",
-    c: "c",
-    d: "d",
-    e: "e",
-    f: undefined,
-  });
-});
-
-test("one to one", () => {
-  const A = z.interface({
-    name: z.string(),
-    get b() {
-      return z._default(z.optional(B), {} as any);
-    },
-  });
-
-  const B = z.interface({
-    name: z.string(),
-    get a() {
-      return A;
-    },
-  });
-
-  interface A {
-    name: string;
-    b: B | undefined;
-  }
-  interface B {
-    name: string;
-    a: A;
-  }
-  expectTypeOf<(typeof A._zod.output)["b"]["a"]["b"]["name"]>().toEqualTypeOf<string>();
-  expectTypeOf<(typeof A._zod.input)["b"]>().toEqualTypeOf<B | undefined>();
-});
-
-test("one to many", () => {
-  const C = z.interface({
-    name: z.string(),
-    get d() {
-      return z.array(D);
-    },
-  });
-
-  const D = z.interface({
-    age: z.number(),
-    get c() {
-      return C;
-    },
-  });
-
-  interface _C {
-    name: string;
-    d: _D[];
-  }
-  interface _D {
-    age: number;
-    c: _C;
-  }
-
-  // ._zod.outputC.d.c.d.c.d;
-  // expectTypeOf<(typeof C)["_def"]["shape"]>().toEqualTypeOf<z.ZodMiniShape>();
-  expectTypeOf<typeof C._zod.output>().toEqualTypeOf<_C>();
-  expectTypeOf<(typeof D._zod.output)["c"]["d"][number]>().toEqualTypeOf<_D>();
-});
-
-test("many to many", () => {
-  const E = z.interface({
-    name: z.string(),
-    get f() {
-      return z.array(F);
-    },
-  });
-
-  const F = z.interface({
-    age: z.number(),
-    get e() {
-      return z.array(E);
-    },
-  });
-
-  interface _E {
-    name: string;
-    f: _F[];
-  }
-  interface _F {
-    age: number;
-    e: _E[];
-  }
-
-  expectTypeOf<typeof E._zod.output>().toEqualTypeOf<_E>();
-  expectTypeOf<(typeof F._zod.output)["e"][number]>().toEqualTypeOf<_E>();
-});
-
-test("self recursive", () => {
-  const E = z.interface({
-    name: z.string(),
-    get e() {
-      return E;
-    },
-  });
-
-  interface _E {
-    name: string;
-    e: _E;
-  }
-  expectTypeOf<(typeof E._zod.output)["e"]["e"]["e"]>().toEqualTypeOf<_E>();
-  E;
-});
-
-test("self recursive optional", () => {
-  const F = z.interface({
-    name: z.string(),
-    get "f?"() {
-      return z.nullable(F);
-    },
-  });
-
-  interface _F {
-    name: string;
-    f?: _F | null;
-  }
-
-  expectTypeOf<typeof F._zod.output>().toEqualTypeOf<_F>();
-
-  expect(z.parse(F, { name: "a", f: null })).toEqual({ name: "a", f: null });
-});
-
-const userSchema = z.interface({
-  name: z.string(),
-  age: z.number(),
-  "email?": z.string(),
-});
-
-test("z.keyof", () => {
-  const userKeysSchema = z.keyof(userSchema);
-  type UserKeys = z.infer<typeof userKeysSchema>;
-  expectTypeOf<UserKeys>().toEqualTypeOf<"name" | "age" | "email">();
-  expect(userKeysSchema).toBeDefined();
-  expect(z.safeParse(userKeysSchema, "name").success).toBe(true);
-  expect(z.safeParse(userKeysSchema, "age").success).toBe(true);
-  expect(z.safeParse(userKeysSchema, "email").success).toBe(true);
-  expect(z.safeParse(userKeysSchema, "isAdmin").success).toBe(false);
-});
-
-// test("z.extend", () => {
-//   const extendedSchema = z.extend(userSchema, {
-//     isAdmin: z.boolean(),
-//   });
-//   type ExtendedUser = z.infer<typeof extendedSchema>;
-//   expectTypeOf<ExtendedUser>().toEqualTypeOf<{
-//     name: string;
-//     age: number;
-//     email?: string;
-//     isAdmin: boolean;
-//   }>();
-//   expect(extendedSchema).toBeDefined();
-//   expect(z.safeParse(extendedSchema, { name: "John", age: 30, isAdmin: true }).success).toBe(true);
-// });
-
-test("z.extend", () => {
-  const a = z.interface({ a: z.string() });
-
-  const b = z.extend(a, z.interface({ b: z.string() }));
-  expectTypeOf(b).toEqualTypeOf<
-    z.ZodMiniInterface<
-      { a: z.ZodMiniString<string>; b: z.ZodMiniString<string> },
-      {
-        optional: never;
-        defaulted: never;
-        extra: {};
-      }
-    >
-  >();
-  z.parse(b, { a: "a", b: "b" });
-  expect(() => z.parse(b, { a: "a" })).toThrow();
-});
-
-test("z.extend with optionals", () => {
-  const a = z.interface({ a: z.string(), "b?": z.string() });
-  const _ = z.interface({ "a?": z.string(), b: z.string() });
-  const b = z.extend(a, _);
-  expectTypeOf(b).toEqualTypeOf<
-    z.ZodMiniInterface<
-      { a: z.ZodMiniString<string>; b: z.ZodMiniString<string> },
-      {
-        optional: "a";
-        defaulted: never;
-        extra: {};
-      }
-    >
-  >();
-  z.parse(b, { a: "a", b: "b" });
-  expect(b._zod.def.optional).toEqual(["a"]);
-  z.parse(b, { b: "b" });
-  expect(() => z.parse(b, { a: "a" })).toThrow();
-});
-
-test("z.extend with optional properties", () => {
-  const a = z.interface({ "a?": z.string(), b: z.string() });
-  const b = z.extend(a, { "?a": z.string(), "b?": z.string() });
-  type b = z.infer<typeof b>;
-  expectTypeOf(b._zod.def.shape).toEqualTypeOf<{
-    a: z.ZodMiniString<string>;
-    b: z.ZodMiniString<string>;
-  }>();
-  expectTypeOf<typeof a._zod.defaulted>().toEqualTypeOf<never>();
-  expectTypeOf<typeof a._zod.optional>().toEqualTypeOf<"a">();
-  expectTypeOf<typeof b._zod.defaulted>().toEqualTypeOf<"a">();
-  expectTypeOf<typeof b._zod.optional>().toEqualTypeOf<"b">();
-  expectTypeOf<b>().toEqualTypeOf<{ a: string; b?: string }>();
-});
-
-test("z.pick", () => {
-  const pickedSchema = z.pick(userSchema, { name: true, email: true });
-  type PickedUser = z.infer<typeof pickedSchema>;
-  expectTypeOf<PickedUser>().toEqualTypeOf<{ name: string; email?: string }>();
-  expect(pickedSchema).toBeDefined();
-  expect(z.safeParse(pickedSchema, { name: "John", email: "john@example.com" }).success).toBe(true);
-});
-
-test("z.omit", () => {
-  const omittedSchema = z.omit(userSchema, { age: true });
-
-  type OmittedUser = z.infer<typeof omittedSchema>;
-  expectTypeOf<OmittedUser>().toEqualTypeOf<{ name: string; email?: string }>();
-  expect(omittedSchema).toBeDefined();
-  expect(z.safeParse(omittedSchema, { name: "John", email: "john@example.com" }).success).toBe(true);
-});
-
-test("z.partial", () => {
-  const partialSchema = z.partial(userSchema);
-  partialSchema._zod.def.type;
-
-  type PartialUser = z.infer<typeof partialSchema>;
-  expectTypeOf<PartialUser>().toEqualTypeOf<{
-    name?: string;
-    age?: number;
-    email?: string;
-  }>();
-  expect(z.safeParse(partialSchema, {}).success).toBe(true);
-  expect(z.safeParse(partialSchema, { name: "foo" }).success).toBe(true);
-  expect(z.safeParse(partialSchema, { age: 123 }).success).toBe(true);
-  expect(z.safeParse(partialSchema, { email: "foo" }).success).toBe(true);
-
-  const partialSchemaWithMask = z.partial(userSchema, { name: true });
-  type PartialUserWithMask = z.infer<typeof partialSchemaWithMask>;
-  expectTypeOf<PartialUserWithMask>().toEqualTypeOf<{
-    name?: string;
-    age: number;
-    email?: string;
-  }>();
-  expect(z.safeParse(partialSchemaWithMask, { age: 30 }).success).toBe(true);
-  expect(z.safeParse(partialSchemaWithMask, { name: "John" }).success).toBe(false);
-});
-
-test("z.required()", () => {
-  const reqSchema = z.required(userSchema);
-  expect(z.parse(reqSchema, { name: "John", age: 30, email: "foo" })).toEqual({
-    name: "John",
-    age: 30,
-    email: "foo",
-  });
-
-  expect(() => z.parse(reqSchema, { age: 30 })).toThrow();
-  expect(() => z.parse(reqSchema, { name: "John" })).toThrow();
-  expect(() => z.parse(reqSchema, { email: "John" })).toThrow();
-  expect(() => z.parse(reqSchema, {})).toThrow();
-});
diff --git a/packages/mini/tests/object.test.ts b/packages/mini/tests/object.test.ts
index d40735da..15a7bc1b 100644
--- a/packages/mini/tests/object.test.ts
+++ b/packages/mini/tests/object.test.ts
@@ -10,7 +10,7 @@ test("z.object", () => {
   });
 
   a._zod.def.shape["test?"];
-  a._zod.def.shape.points._zod.qout;
+  a._zod.def.shape.points._zod.optionality;
 
   type a = z.output<typeof a>;
 
@@ -124,7 +124,9 @@ test("z.partial", () => {
     email?: string;
   }>();
   expect(z.safeParse(partialSchema, { name: "John" }).success).toBe(true);
+});
 
+test("z.partial with mask", () => {
   const partialSchemaWithMask = z.partial(userSchema, { name: true });
   type PartialUserWithMask = z.infer<typeof partialSchemaWithMask>;
   expectTypeOf<PartialUserWithMask>().toEqualTypeOf<{
diff --git a/packages/zod/tests/brand.test.ts b/packages/zod/tests/brand.test.ts
index d861f50b..957a6a70 100644
--- a/packages/zod/tests/brand.test.ts
+++ b/packages/zod/tests/brand.test.ts
@@ -11,7 +11,7 @@ test("branded types", () => {
   // simple branding
   type MySchema = z.infer<typeof mySchema>;
 
-  expectTypeOf<MySchema>().toEqualTypeOf<{ name: string } & z.BRAND<"superschema">>();
+  expectTypeOf<MySchema>().toEqualTypeOf<{ name: string } & z.$brand<"superschema">>();
 
   const doStuff = (arg: MySchema) => arg;
   doStuff(mySchema.parse({ name: "hello there" }));
diff --git a/packages/zod/tests/default.test.ts b/packages/zod/tests/default.test.ts
index 1a950f9e..fd0d1f75 100644
--- a/packages/zod/tests/default.test.ts
+++ b/packages/zod/tests/default.test.ts
@@ -112,17 +112,3 @@ test("object optionality", () => {
     hi: "hi",
   });
 });
-
-test("interface optionality", () => {
-  const schema = z.interface({
-    "?hi": z.string().default("hi"),
-  });
-
-  expect(
-    schema.parse({
-      hi: "hi",
-    })
-  ).toEqual({
-    hi: "hi",
-  });
-});
diff --git a/packages/zod/tests/discriminated-unions.test.ts b/packages/zod/tests/discriminated-unions.test.ts
index 7c786bc1..da219f5e 100644
--- a/packages/zod/tests/discriminated-unions.test.ts
+++ b/packages/zod/tests/discriminated-unions.test.ts
@@ -37,17 +37,6 @@ test("valid parse - object", () => {
   ).toEqual({ type: "a", a: "abc" });
 });
 
-test("valid parse - interface", () => {
-  expect(
-    z
-      .discriminatedUnion([
-        z.interface({ type: z.literal("a"), a: z.string() }),
-        z.interface({ type: z.literal("b"), b: z.string() }),
-      ])
-      .parse({ type: "a", a: "abc" })
-  ).toEqual({ type: "a", a: "abc" });
-});
-
 test("valid - include discriminator key (deprecated)", () => {
   expect(
     z
@@ -68,16 +57,6 @@ test("valid - optional discriminator (object)", () => {
   expect(schema.parse({ a: "abc" })).toEqual({ a: "abc" });
 });
 
-test("valid - optional discriminator (interface)", () => {
-  const schema = z.discriminatedUnion([
-    z.interface({ type: z.literal("a").optional(), a: z.string() }),
-    z.interface({ type: z.literal("b"), b: z.string() }),
-  ]);
-  expect(schema.parse({ type: "a", a: "abc" })).toEqual({ type: "a", a: "abc" });
-  expect(schema.parse({ type: undefined, a: "abc" })).toEqual({ type: undefined, a: "abc" });
-  expect(schema.parse({ type: "b", b: "abc" })).toEqual({ type: "b", b: "abc" });
-});
-
 test("valid - discriminator value of various primitive types", () => {
   const schema = z.discriminatedUnion([
     z.object({ type: z.literal("1"), val: z.string() }),
diff --git a/packages/zod/tests/firstparty.test.ts b/packages/zod/tests/firstparty.test.ts
index 9251ae48..63ac26b2 100644
--- a/packages/zod/tests/firstparty.test.ts
+++ b/packages/zod/tests/firstparty.test.ts
@@ -34,8 +34,6 @@ test("first party switch", () => {
       break;
     case "object":
       break;
-    case "interface":
-      break;
     case "union":
       break;
     case "intersection":
diff --git a/packages/zod/tests/interface.test.ts b/packages/zod/tests/interface.test.ts
deleted file mode 100644
index 1f5a75de..00000000
--- a/packages/zod/tests/interface.test.ts
+++ /dev/null
@@ -1,419 +0,0 @@
-import { expect, expectTypeOf, test } from "vitest";
-
-import * as z from "zod";
-
-test("object type inference", () => {
-  const Test = z.interface({
-    f1: z.number(),
-    "f2?": z.string(),
-    f3: z.string().nullable(),
-    f4: z.array(z.interface({ t: z.union([z.string(), z.boolean()]) })),
-  });
-
-  type Test = z.output<typeof Test>;
-  type TestType = {
-    f1: number;
-    f2?: string | undefined;
-    f3: string | null;
-    f4: { t: string | boolean }[];
-  };
-
-  expectTypeOf<Test>().toEqualTypeOf<TestType>();
-
-  const data = {
-    f1: 12,
-    f2: "string",
-    f3: "string",
-    f4: [
-      {
-        t: "string",
-      },
-    ],
-  };
-  expect(Test.parse(data)).toEqual(data);
-  expect(Test.safeParse("foo")).toMatchObject({ success: false });
-});
-
-// test("shape() should return schema of particular key", () => {
-//   const schema = z.interface({
-//     name: z.string(),
-//   });
-
-//   expect(schema.shape.name).toBeInstanceOf(z.ZodString);
-// });
-
-test("optional with .optional()", () => {
-  const schema = z.interface({
-    a: z.string().optional(),
-  });
-
-  expect(schema.parse({})).toEqual({ a: undefined });
-  expect(schema.parse({ a: undefined })).toEqual({ a: undefined });
-});
-
-test("question mark optional", () => {
-  const schema = z.interface({
-    "a?": z.string().optional(),
-  });
-  expect(schema.parse({})).toEqual({});
-  expect("a" in schema.parse({})).toEqual(false);
-  expect(schema.parse({ a: undefined })).toEqual({ a: undefined });
-  expect("a" in schema.parse({ a: undefined })).toEqual(true);
-  expect(schema.parse({ a: "foo" })).toEqual({ a: "foo" });
-});
-
-test("default in optional key", () => {
-  const schema = z.interface({
-    "name?": z.string().default("tuna"),
-  });
-  expect(schema.parse({}).name).toEqual("tuna");
-  expect(schema.parse({ name: undefined }).name).toEqual("tuna");
-});
-
-test("defaulted key", () => {
-  const schema = z.interface({
-    "?a": z.string().default("asdf"),
-  });
-
-  expectTypeOf<typeof schema._zod.input>().toEqualTypeOf<{ a?: string }>();
-  expectTypeOf<typeof schema._zod.output>().toEqualTypeOf<{ a: string }>();
-  expect(schema.parse({})).toEqual({ a: "asdf" });
-  expect(schema.parse({ a: undefined })).toEqual({ a: "asdf" });
-});
-
-test("z.interface - strip by default", () => {
-  const schema = z.interface({ points: z.number() });
-  const data = { points: 2314, unknown: "asdf" };
-  const result = schema.safeParse(data);
-  expect(result.data).toEqual({ points: 2314 });
-});
-
-test("z.looseInterface", () => {
-  const schema = z.looseInterface({ points: z.number() });
-  const data = { points: 2314, unknown: "asdf" };
-  const val = schema.parse(data);
-  expect(val).toEqual(data);
-});
-
-test("strict", () => {
-  const schema = z.strictInterface({ points: z.number() });
-  const data = { points: 2314, unknown: "asdf" };
-  const val = schema.safeParse(data);
-  expect(val.success).toEqual(false);
-});
-
-test("catchall", () => {
-  const schema = z
-    .interface({
-      first: z.string(),
-    })
-    .catchall(z.number());
-
-  const d1 = schema.safeParse({ first: "asdf", num: 1243 });
-  expect(d1.data).toEqual({ first: "asdf", num: 1243 });
-
-  const d2 = schema.safeParse({ first: "asdf", num: "asdf" });
-  expect(d2.success).toEqual(false);
-});
-
-test("catchall overrides strict", () => {
-  const schema = z.strictInterface({ first: z.string().optional() }).catchall(z.number());
-
-  // setting a catchall overrides the unknownKeys behavior
-  schema.parse({ asdf: 1234 });
-});
-
-test("only run catchall on unknown keys", () => {
-  const schema = z.strictInterface({ first: z.string().optional() }).catchall(z.number());
-  schema.parse({
-    first: "asdf",
-    asdf: 1234,
-  });
-});
-
-test("extend overrides existing", async () => {
-  const a = z.interface({ a: z.string() });
-  const b = z.interface({ a: z.number() });
-  const c = a.extend(b);
-  type c = z.infer<typeof c>;
-  expectTypeOf<c>().toEqualTypeOf<{ a: number }>();
-});
-
-test("extend overrides optionality", async () => {
-  const a = z.interface({ "?a": z.string(), "b?": z.string() });
-  const b = z.interface({ a: z.string(), b: z.string() });
-  const c = a.extend(b);
-
-  type c = z.infer<typeof c>;
-  expectTypeOf<c>().toEqualTypeOf<{ a: string; b: string }>();
-
-  const aData = { a: "asdf" };
-  expect(a.parse(aData)).toEqual(aData);
-
-  expect(c.safeParse(aData).success).toEqual(false);
-
-  const cData = { a: "asdf", b: "asdf" };
-  expect(c.parse(cData)).toEqual(cData);
-});
-
-test("inferred merged object type with optional properties", async () => {
-  const a = z.interface({ "a?": z.string(), b: z.string().optional() });
-  const b = z.interface({ a: z.string().optional(), "b?": z.string() });
-  const c = a.merge(b);
-  // c.shape;
-  type c = z.infer<typeof c>;
-  expectTypeOf<c>().toEqualTypeOf<{ a: string | undefined; b?: string }>();
-  expectTypeOf<typeof a>().toMatchTypeOf<z.ZodInterface>();
-});
-
-// declare let xx: z.ZodInterface<{a: z.ZodString}>;
-// xx._output;
-test("inferred unioned object type with optional properties", async () => {
-  const Unioned = z.union([
-    z.interface({ a: z.string(), "b?": z.string().optional() }),
-    z.interface({ "a?": z.string().optional(), b: z.string() }),
-  ]);
-  type Unioned = z.infer<typeof Unioned>;
-  expectTypeOf<Unioned>().toEqualTypeOf<{ a: string; b?: string } | { a?: string; b: string }>();
-});
-
-test("inferred enum type", async () => {
-  const Enum = z.interface({ a: z.string(), b: z.string().optional() }).keyof();
-
-  expect(Enum.enum).toEqual({
-    a: "a",
-    b: "b",
-  });
-
-  expect(Enum._zod.def.entries).toEqual({
-    a: "a",
-    b: "b",
-  });
-  type Enum = z.infer<typeof Enum>;
-  expectTypeOf<Enum>().toEqualTypeOf<"a" | "b">();
-});
-
-test(".partial", async () => {
-  const Partial = z.interface({ a: z.string(), b: z.string().optional() }).partial();
-  type Partial = z.infer<typeof Partial>;
-  expectTypeOf<Partial>().toEqualTypeOf<{ a?: string; b?: string }>();
-  expect(Partial._zod.def.shape.a).toBeInstanceOf(z.ZodOptional);
-  expect(Partial._zod.def.shape.b).toBeInstanceOf(z.ZodOptional);
-  expect(Partial._zod.def.optional).toEqual(["a", "b"]);
-});
-
-test(".required", async () => {
-  const Required = z
-    .interface({ a: z.string(), b: z.string().optional(), "c?": z.string(), "?d": z.string() })
-    .required();
-  type Required = z.infer<typeof Required>;
-  expectTypeOf<Required>().toEqualTypeOf<{ a: string; b: string; c: string; d: string }>();
-  expectTypeOf<typeof Required._zod.optional>().toEqualTypeOf<never>();
-  expectTypeOf<typeof Required._zod.defaulted>().toEqualTypeOf<"d">();
-  expect(Required._zod.def.shape.a).toBeInstanceOf(z.ZodNonOptional);
-  expect(Required._zod.def.shape.b).toBeInstanceOf(z.ZodNonOptional);
-  expect(Required._zod.def.shape.c).toBeInstanceOf(z.ZodNonOptional);
-  expect(Required._zod.def.shape.d).toBeInstanceOf(z.ZodNonOptional);
-  expect(Required._zod.def.optional).toEqual([]);
-  // expect(Required._zod.def.defaulted).toEqual(["d"]);
-});
-
-test("inferred picked object type with optional properties", async () => {
-  const Picked = z.interface({ a: z.string(), "b?": z.string() }).pick({ b: true });
-  type Picked = z.infer<typeof Picked>;
-  expectTypeOf<Picked>().toEqualTypeOf<{ b?: string }>();
-});
-
-test("inferred type for unknown/any keys", () => {
-  const myType = z.interface({
-    anyOptional: z.any().optional(),
-    anyRequired: z.any(),
-    unknownOptional: z.unknown().optional(),
-    unknownRequired: z.unknown(),
-  });
-  type myType = z.infer<typeof myType>;
-  expectTypeOf<myType>().toEqualTypeOf<{
-    anyOptional: any;
-    anyRequired: any;
-    unknownOptional: unknown;
-    unknownRequired: unknown;
-  }>();
-
-  const myType2 = z.interface({
-    "anyOptional?": z.any().optional(),
-    "anyRequired?": z.any(),
-    "unknownOptional?": z.unknown().optional(),
-    "unknownRequired?": z.unknown(),
-  });
-  type myType2 = z.infer<typeof myType2>;
-  expectTypeOf<myType2>().toEqualTypeOf<{
-    anyOptional?: any;
-    anyRequired?: any;
-    unknownOptional?: unknown;
-    unknownRequired?: unknown;
-  }>();
-});
-
-// test("setKey", () => {
-//   const base = z.interface({ name: z.string() });
-//   const withNewKey = base.setKey("age", z.number());
-
-//   type withNewKey = z.infer<typeof withNewKey>;
-//   expectTypeOf<withNewKey>().toEqualTypeOf<{ name: string; age: number }>();
-//   withNewKey.parse({ name: "asdf", age: 1234 });
-// });
-
-test("strictObject", async () => {
-  const strictObj = z.strictObject({
-    name: z.string(),
-  });
-
-  const syncResult = strictObj.safeParse({ name: "asdf", unexpected: 13 });
-  expect(syncResult.success).toEqual(false);
-
-  const asyncResult = await strictObj.spa({ name: "asdf", unexpected: 13 });
-  expect(asyncResult.success).toEqual(false);
-});
-
-test("object with refine", async () => {
-  const schema = z
-    .interface({
-      a: z.string().default("foo"),
-      b: z.number(),
-    })
-    .refine(() => true);
-  expect(schema.parse({ b: 5 })).toEqual({ b: 5, a: "foo" });
-  const result = await schema.parseAsync({ b: 5 });
-  expect(result).toEqual({ b: 5, a: "foo" });
-});
-
-test("intersection of object with date", async () => {
-  const schema = z.interface({
-    a: z.date(),
-  });
-  expect(z.intersection(schema, schema).parse({ a: new Date(1637353595983) })).toEqual({
-    a: new Date(1637353595983),
-  });
-  const result = await schema.parseAsync({ a: new Date(1637353595983) });
-  expect(result).toEqual({ a: new Date(1637353595983) });
-});
-
-test("intersection of object with refine with date", async () => {
-  const schema = z
-    .interface({
-      a: z.date(),
-    })
-    .refine(() => true);
-  expect(z.intersection(schema, schema).parse({ a: new Date(1637353595983) })).toEqual({
-    a: new Date(1637353595983),
-  });
-  const result = await schema.parseAsync({ a: new Date(1637353595983) });
-  expect(result).toEqual({ a: new Date(1637353595983) });
-});
-
-test("strictInterface", () => {
-  const person = z.strictInterface({
-    name: z.string(),
-  });
-
-  expect(() =>
-    person.parse({
-      name: "bob dylan",
-      constructor: 61,
-    })
-  ).toThrow();
-});
-
-test("catchall", () => {
-  const a = z.interface({});
-  expect(a._zod.def.catchall).toBeUndefined();
-
-  const b = z.strictObject({});
-  expect(b._zod.def.catchall).toBeInstanceOf(z.ZodNever);
-
-  const c = z.looseObject({});
-  expect(c._zod.def.catchall).toBeInstanceOf(z.ZodUnknown);
-
-  const d = z.interface({}).catchall(z.number());
-  expect(d._zod.def.catchall).toBeInstanceOf(z.ZodNumber);
-});
-
-test("unknownkeys merging", () => {
-  // This one is "strict"
-  const a = z.looseObject({
-    a: z.string(),
-  });
-
-  const b = z.strictObject({ b: z.string() });
-
-  // incoming object overrides
-  const c = a.merge(b);
-  expect(c._zod.def.catchall).toBeInstanceOf(z.ZodNever);
-
-  // // This one is "strip"
-  // const schemaB = z
-  //   .interface({
-  //     b: z.string(),
-  //   })
-  //   .catchall(z.string());
-
-  // const mergedSchema = schemaA.merge(schemaB);
-  // type mergedSchema = typeof mergedSchema;
-  // // expectTypeOf<mergedSchema["_def"].catchall>().toEqualTypeOf<"strip">(true);
-  // expect(mergedSchema._zod.def.catchall).toBeInstanceOf(z.ZodUnknown);
-
-  // expectTypeOf<mergedSchema["_def"]["catchall"]>().toEqualTypeOf<z.ZodString>(true);
-  // expect(mergedSchema._zod.def.catchall instanceof z.ZodString).toEqual(true);
-});
-
-const personToExtend = z.interface({
-  firstName: z.string(),
-  lastName: z.string(),
-});
-
-test("extend() should return schema with new key", () => {
-  const PersonWithNickname = personToExtend.extend({ nickName: z.string() });
-  type PersonWithNickname = z.infer<typeof PersonWithNickname>;
-
-  const expected = { firstName: "f", nickName: "n", lastName: "l" };
-  const actual = PersonWithNickname.parse(expected);
-
-  expect(actual).toEqual(expected);
-  expectTypeOf<keyof PersonWithNickname>().toEqualTypeOf<"firstName" | "lastName" | "nickName">();
-  expectTypeOf<PersonWithNickname>().toEqualTypeOf<{ firstName: string; lastName: string; nickName: string }>();
-});
-
-test("extend() should have power to override existing key", () => {
-  const PersonWithNumberAsLastName = personToExtend.extend({
-    lastName: z.number(),
-  });
-  type PersonWithNumberAsLastName = z.infer<typeof PersonWithNumberAsLastName>;
-
-  const expected = { firstName: "f", lastName: 42 };
-  const actual = PersonWithNumberAsLastName.parse(expected);
-
-  expect(actual).toEqual(expected);
-  expectTypeOf<PersonWithNumberAsLastName>().toEqualTypeOf<{ firstName: string; lastName: number }>();
-});
-
-// test("passthrough index signature", () => {
-//   const a = z.interface({ a: z.string() });
-//   type a = z.infer<typeof a>;
-//   expectTypeOf<{ a: string }>().toEqualTypeOf<a>(true);
-//   const b = a.passthrough();
-//   type b = z.infer<typeof b>;
-//   expectTypeOf<{ a: string } & { [k: string]: unknown }>().toEqualTypeOf<b>(true);
-// });
-
-test("xor", () => {
-  type Without<T, U> = { [P in Exclude<keyof T, keyof U>]?: never };
-  type XOR<T, U> = T extends object ? (U extends object ? (Without<T, U> & U) | (Without<U, T> & T) : U) : T;
-
-  type A = { name: string; a: number };
-  type B = { name: string; b: number };
-  type C = XOR<A, B>;
-  type Outer = { data: C };
-  const _Outer: z.ZodType<Outer> = z.interface({
-    data: z.union([z.interface({ name: z.string(), a: z.number() }), z.interface({ name: z.string(), b: z.number() })]),
-  });
-});
diff --git a/packages/zod/tests/json-schema.test.ts b/packages/zod/tests/json-schema.test.ts
index b050897f..17d1ef76 100644
--- a/packages/zod/tests/json-schema.test.ts
+++ b/packages/zod/tests/json-schema.test.ts
@@ -658,10 +658,9 @@ describe("toJSONSchema", () => {
   });
 
   test("simple interface", () => {
-    const userSchema = z.interface({
+    const userSchema = z.object({
       name: z.string(),
-      "age?": z.number(),
-      "?email": z.string(),
+      age: z.number().optional(),
     });
 
     const result = toJSONSchema(userSchema);
@@ -671,16 +670,12 @@ describe("toJSONSchema", () => {
           "age": {
             "type": "number",
           },
-          "email": {
-            "type": "string",
-          },
           "name": {
             "type": "string",
           },
         },
         "required": [
           "name",
-          "email",
         ],
         "type": "object",
       }
@@ -688,7 +683,7 @@ describe("toJSONSchema", () => {
   });
 
   test("catchall interface", () => {
-    const a = z.strictInterface({
+    const a = z.strictObject({
       name: z.string(),
       age: z.number(),
     });
@@ -715,7 +710,7 @@ describe("toJSONSchema", () => {
     `);
 
     const b = z
-      .interface({
+      .object({
         name: z.string(),
       })
       .catchall(z.string());
@@ -737,7 +732,7 @@ describe("toJSONSchema", () => {
       }
     `);
 
-    const c = z.looseInterface({
+    const c = z.looseObject({
       name: z.string(),
     });
 
@@ -758,7 +753,7 @@ describe("toJSONSchema", () => {
   });
 
   test("recursive interface schemas", () => {
-    const TreeNodeSchema = z.interface({
+    const TreeNodeSchema = z.object({
       id: z.string(),
       get children() {
         return TreeNodeSchema;
@@ -790,14 +785,14 @@ describe("toJSONSchema", () => {
   });
 
   test("mutually recursive interface schemas", () => {
-    const FolderSchema = z.interface({
+    const FolderSchema = z.object({
       name: z.string(),
       get files() {
         return z.array(FileSchema);
       },
     });
 
-    const FileSchema = z.interface({
+    const FileSchema = z.object({
       name: z.string(),
       get parent() {
         return FolderSchema;
@@ -1179,16 +1174,22 @@ test("overwrite descriptions", () => {
       reused: "ref",
     }
   );
-  expect(a).toMatchInlineSnapshot(`
+  expect(b).toMatchInlineSnapshot(`
     {
+      "$defs": {
+        "__schema0": {
+          "description": "c",
+          "type": "string",
+        },
+      },
       "properties": {
         "d": {
+          "$ref": "#/$defs/__schema0",
           "description": "d",
-          "type": "string",
         },
         "e": {
+          "$ref": "#/$defs/__schema0",
           "description": "e",
-          "type": "string",
         },
       },
       "required": [
@@ -1202,7 +1203,7 @@ test("overwrite descriptions", () => {
 
 test("top-level readonly", () => {
   const A = z
-    .interface({
+    .object({
       name: z.string(),
       get b() {
         return B;
@@ -1212,7 +1213,7 @@ test("top-level readonly", () => {
     .meta({ id: "A" });
 
   const B = z
-    .interface({
+    .object({
       name: z.string(),
       get a() {
         return A;
@@ -1264,14 +1265,14 @@ test("top-level readonly", () => {
 
 test("basic registry", () => {
   const myRegistry = z.registry<{ id: string }>();
-  const User = z.interface({
+  const User = z.object({
     name: z.string(),
     get posts() {
       return z.array(Post);
     },
   });
 
-  const Post = z.interface({
+  const Post = z.object({
     title: z.string(),
     content: z.string(),
     get author() {
@@ -1327,3 +1328,102 @@ test("basic registry", () => {
     }
   `);
 });
+
+test("_ref", () => {
+  // const a = z.promise(z.string().describe("a"));
+  const a = z.toJSONSchema(z.promise(z.string().describe("a")));
+  expect(a).toMatchInlineSnapshot(`
+    {
+      "description": "a",
+      "type": "string",
+    }
+  `);
+
+  const b = z.toJSONSchema(z.lazy(() => z.string().describe("a")));
+  expect(b).toMatchInlineSnapshot(`
+    {
+      "description": "a",
+      "type": "string",
+    }
+  `);
+
+  const c = z.toJSONSchema(z.optional(z.string().describe("a")));
+  expect(c).toMatchInlineSnapshot(`
+    {
+      "description": "a",
+      "type": "string",
+    }
+  `);
+});
+
+test("input type", () => {
+  const schema = z.object({
+    a: z.string(),
+    b: z.string().optional(),
+    c: z.string().default("hello"),
+    d: z.string().nullable(),
+  });
+  expect(toJSONSchema(schema, { io: "input" })).toMatchInlineSnapshot(`
+    {
+      "properties": {
+        "a": {
+          "type": "string",
+        },
+        "b": {
+          "type": "string",
+        },
+        "c": {
+          "default": "hello",
+          "type": "string",
+        },
+        "d": {
+          "anyOf": [
+            {
+              "type": "string",
+            },
+            {
+              "type": "null",
+            },
+          ],
+        },
+      },
+      "required": [
+        "a",
+        "d",
+      ],
+      "type": "object",
+    }
+  `);
+  expect(toJSONSchema(schema, { io: "output" })).toMatchInlineSnapshot(`
+    {
+      "properties": {
+        "a": {
+          "type": "string",
+        },
+        "b": {
+          "type": "string",
+        },
+        "c": {
+          "default": "hello",
+          "type": "string",
+        },
+        "d": {
+          "anyOf": [
+            {
+              "type": "string",
+            },
+            {
+              "type": "null",
+            },
+          ],
+        },
+      },
+      "required": [
+        "a",
+        "c",
+        "d",
+      ],
+      "type": "object",
+    }
+  `);
+});
diff --git a/packages/zod/tests/lazy.test.ts b/packages/zod/tests/lazy.test.ts
index 457a53a4..466d4622 100644
--- a/packages/zod/tests/lazy.test.ts
+++ b/packages/zod/tests/lazy.test.ts
@@ -2,7 +2,7 @@ import { expect, expectTypeOf, test } from "vitest";
 
 import * as z from "zod";
 
-test("qin qout passthrough", () => {
+test("opt passthrough", () => {
   const object = z.object({
     a: z.lazy(() => z.string()),
     b: z.lazy(() => z.string().optional()),
@@ -36,11 +36,167 @@ test("qin qout passthrough", () => {
     c: "default",
   });
 
-  const lazyString = z.lazy(() => z.string().optional());
-  expect(lazyString._zod.qout).toEqual("true");
-  expect(object._zod.def.optional).toMatchInlineSnapshot(`
-    [
-      "b",
-    ]
-  `);
+  expect(z.lazy(() => z.string())._zod.optionality).toEqual(undefined);
+  expect(z.lazy(() => z.string().optional())._zod.optionality).toEqual("optional");
+  expect(z.lazy(() => z.string().default("asdf"))._zod.optionality).toEqual("defaulted");
+});
+
+//////////////   LAZY   //////////////
+
+test("schema getter", () => {
+  z.lazy(() => z.string()).parse("asdf");
+});
+
+test("lazy proxy", () => {
+  const schema = z.lazy(() => z.string())._zod._getter.min(6);
+  schema.parse("123456");
+  expect(schema.safeParse("12345").success).toBe(false);
+});
+
+interface Category {
+  name: string;
+  subcategories: Category[];
+}
+
+const testCategory: Category = {
+  name: "I",
+  subcategories: [
+    {
+      name: "A",
+      subcategories: [
+        {
+          name: "1",
+          subcategories: [
+            {
+              name: "a",
+              subcategories: [],
+            },
+          ],
+        },
+      ],
+    },
+  ],
+};
+
+test("recursion with z.lazy", () => {
+  const Category: z.ZodType<Category> = z.lazy(() =>
+    z.object({
+      name: z.string(),
+      subcategories: z.array(Category),
+    })
+  );
+  Category.parse(testCategory);
+});
+
+type LinkedList = null | { value: number; next: LinkedList };
+
+const linkedListExample = {
+  value: 1,
+  next: {
+    value: 2,
+    next: {
+      value: 3,
+      next: {
+        value: 4,
+        next: null,
+      },
+    },
+  },
+};
+
+test("recursive union wit z.lazy", () => {
+  const LinkedListSchema: z.ZodType<LinkedList> = z.lazy(() =>
+    z.union([
+      z.null(),
+      z.object({
+        value: z.number(),
+        next: LinkedListSchema,
+      }),
+    ])
+  );
+  LinkedListSchema.parse(linkedListExample);
+});
+
+interface A {
+  val: number;
+  b: B;
+}
+
+interface B {
+  val: number;
+  a?: A | undefined;
+}
+
+test("mutual recursion with lazy", () => {
+  const Alazy: z.ZodType<A> = z.lazy(() =>
+    z.object({
+      val: z.number(),
+      b: Blazy,
+    })
+  );
+
+  const Blazy: z.ZodType<B> = z.lazy(() =>
+    z.object({
+      val: z.number(),
+      a: Alazy.optional(),
+    })
+  );
+
+  const testData = {
+    val: 1,
+    b: {
+      val: 5,
+      a: {
+        val: 3,
+        b: {
+          val: 4,
+          a: {
+            val: 2,
+            b: {
+              val: 1,
+            },
+          },
+        },
+      },
+    },
+  };
+
+  Alazy.parse(testData);
+  Blazy.parse(testData.b);
+
+  expect(() => Alazy.parse({ val: "asdf" })).toThrow();
+});
+
+// TODO
+test("mutual recursion with cyclical data", () => {
+  const a: any = { val: 1 };
+  const b: any = { val: 2 };
+  a.b = b;
+  b.a = a;
+});
+
+test("complicated self-recursion", () => {
+  const Category = z.object({
+    name: z.string(),
+    age: z.optional(z.number()),
+    get nullself() {
+      return Category.nullable();
+    },
+    get optself() {
+      return Category.optional();
+    },
+    get self() {
+      return Category;
+    },
+    get subcategories() {
+      return z.array(Category);
+    },
+    nested: z.object({
+      get sub() {
+        return Category;
+      },
+    }),
+  });
+
+  type _Category = z.output<typeof Category>;
 });
diff --git a/packages/zod/tests/object.test.ts b/packages/zod/tests/object.test.ts
index 46283b7a..d07a2466 100644
--- a/packages/zod/tests/object.test.ts
+++ b/packages/zod/tests/object.test.ts
@@ -80,7 +80,7 @@ test("empty object", () => {
   expect(schema.parse({ name: "asdf" })).toEqual({});
   expect(schema.safeParse(null).success).toEqual(false);
   expect(schema.safeParse("asdf").success).toEqual(false);
-  expectTypeOf<typeof schema._zod.output>().toEqualTypeOf<object>();
+  expectTypeOf<z.output<typeof schema>>().toEqualTypeOf<object>();
 });
 
 const data = {
@@ -213,6 +213,7 @@ test("test async union", async () => {
 test("test inferred merged type", async () => {
   const asdf = z.object({ a: z.string() }).merge(z.object({ a: z.number() }));
   type asdf = z.infer<typeof asdf>;
+
   expectTypeOf<asdf>().toEqualTypeOf<{ a: number }>();
 });
 
@@ -433,12 +434,12 @@ test("passthrough index signature", () => {
 // });
 
 test("assignability", () => {
-  z.interface({ a: z.string() }) satisfies z.ZodInterface;
-  z.interface({ a: z.string() }).catchall(z.number()) satisfies z.ZodInterface;
-  z.interface({ a: z.string() }).strict() satisfies z.ZodInterface;
-  z.interface({}) satisfies z.ZodInterface;
-  z.interface({ "a?": z.string() }) satisfies z.ZodInterface;
-  z.interface({ "?a": z.string() }) satisfies z.ZodInterface;
+  z.object({ a: z.string() }) satisfies z.ZodObject;
+  z.object({ a: z.string() }).catchall(z.number()) satisfies z.ZodObject;
+  z.object({ a: z.string() }).strict() satisfies z.ZodObject;
+  z.object({}) satisfies z.ZodObject;
+  z.object({ "a?": z.string() }) satisfies z.ZodObject;
+  z.object({ "?a": z.string() }) satisfies z.ZodObject;
 });
 
 test("null prototype", () => {
diff --git a/packages/zod/tests/partial-interface.test.ts b/packages/zod/tests/partial-interface.test.ts
deleted file mode 100644
index 907ba4c7..00000000
--- a/packages/zod/tests/partial-interface.test.ts
+++ /dev/null
@@ -1,147 +0,0 @@
-import { expect, expectTypeOf, test } from "vitest";
-import * as z from "zod";
-
-const nested = z.interface({
-  name: z.string(),
-  age: z.number(),
-  outer: z.interface({
-    inner: z.string(),
-  }),
-  array: z.array(z.interface({ asdf: z.string() })),
-});
-
-test("shallow inference", () => {
-  const shallow = nested.partial();
-  type shallow = z.infer<typeof shallow>;
-
-  expectTypeOf<shallow>().toEqualTypeOf<{
-    name?: string | undefined;
-    age?: number | undefined;
-    outer?: { inner: string } | undefined;
-    array?: { asdf: string }[] | undefined;
-  }>();
-});
-
-test("shallow partial parse", () => {
-  const shallow = nested.partial();
-  shallow.parse({});
-  shallow.parse({
-    name: "asdf",
-    age: 23143,
-  });
-});
-
-test("required", () => {
-  const object = z.interface({
-    name: z.string(),
-    age: z.number().optional(),
-    field: z.string().optional().default("asdf"),
-    nullableField: z.number().nullable(),
-    nullishField: z.string().nullish(),
-  });
-
-  const requiredObject = object.required();
-  expect(requiredObject._zod.def.shape.name).toBeInstanceOf(z.ZodNonOptional);
-  expect(requiredObject._zod.def.shape.name.unwrap()).toBeInstanceOf(z.ZodString);
-  expect(requiredObject._zod.def.shape.age).toBeInstanceOf(z.ZodNonOptional);
-  expect(requiredObject._zod.def.shape.age.unwrap()).toBeInstanceOf(z.ZodOptional);
-  expect(requiredObject._zod.def.shape.field).toBeInstanceOf(z.ZodNonOptional);
-  expect(requiredObject._zod.def.shape.field.unwrap()).toBeInstanceOf(z.ZodDefault);
-  expect(requiredObject._zod.def.shape.nullableField).toBeInstanceOf(z.ZodNonOptional);
-  expect(requiredObject._zod.def.shape.nullableField.unwrap()).toBeInstanceOf(z.ZodNullable);
-  expect(requiredObject._zod.def.shape.nullishField).toBeInstanceOf(z.ZodNonOptional);
-  expect(requiredObject._zod.def.shape.nullishField.unwrap()).toBeInstanceOf(z.ZodOptional);
-  expect(requiredObject._zod.def.shape.nullishField.unwrap().unwrap()).toBeInstanceOf(z.ZodNullable);
-});
-
-test("required inference", () => {
-  const object = z.interface({
-    name: z.string(),
-    age: z.number().optional(),
-    field: z.string().optional().default("asdf"),
-    nullableField: z.number().nullable(),
-    nullishField: z.string().nullish(),
-  });
-
-  const requiredObject = object.required();
-
-  type required = z.infer<typeof requiredObject>;
-  type expected = {
-    name: string;
-    age: number;
-    field: string;
-    nullableField: number | null;
-    nullishField: string | null;
-  };
-  expectTypeOf<expected>().toEqualTypeOf<required>();
-});
-
-test("required with mask", () => {
-  const object = z.interface({
-    name: z.string(),
-    age: z.number().optional(),
-    field: z.string().optional().default("asdf"),
-    country: z.string().optional(),
-  });
-
-  const requiredObject = object.required({ age: true });
-  expect(requiredObject._zod.def.shape.name).toBeInstanceOf(z.ZodString);
-  expect(requiredObject._zod.def.shape.age).toBeInstanceOf(z.ZodNonOptional);
-  expect(requiredObject._zod.def.shape.field).toBeInstanceOf(z.ZodDefault);
-  expect(requiredObject._zod.def.shape.country).toBeInstanceOf(z.ZodOptional);
-});
-
-test("required with mask -- ignore falsy values", () => {
-  const object = z.interface({
-    name: z.string(),
-    age: z.number().optional(),
-    field: z.string().optional().default("asdf"),
-    country: z.string().optional(),
-  });
-
-  // @ts-expect-error
-  const requiredObject = object.required({ age: true, country: false });
-  expect(requiredObject._zod.def.shape.name).toBeInstanceOf(z.ZodString);
-  expect(requiredObject._zod.def.shape.age).toBeInstanceOf(z.ZodNonOptional);
-  expect(requiredObject._zod.def.shape.field).toBeInstanceOf(z.ZodDefault);
-  expect(requiredObject._zod.def.shape.country).toBeInstanceOf(z.ZodOptional);
-});
-
-test("partial with mask", async () => {
-  const object = z.interface({
-    name: z.string(),
-    age: z.number().optional(),
-    field: z.string().optional().default("asdf"),
-    country: z.string(),
-  });
-
-  const masked = object.partial({ age: true, field: true, name: true }).strict();
-
-  expect(masked._zod.def.shape.name).toBeInstanceOf(z.ZodOptional);
-  expect(masked._zod.def.shape.age).toBeInstanceOf(z.ZodOptional);
-  expect(masked._zod.def.shape.field).toBeInstanceOf(z.ZodOptional);
-  expect(masked._zod.def.shape.country).toBeInstanceOf(z.ZodString);
-
-  masked.parse({ country: "US" });
-  await masked.parseAsync({ country: "US" });
-});
-
-test("partial with mask -- ignore falsy values", async () => {
-  const object = z.interface({
-    name: z.string(),
-    age: z.number().optional(),
-    field: z.string().optional().default("asdf"),
-    country: z.string(),
-  });
-
-  // @ts-expect-error
-  const masked = object.partial({ name: true, country: false }).strict();
-
-  expect(masked._zod.def.shape.name).toBeInstanceOf(z.ZodOptional);
-  expect(masked._zod.def.shape.age).toBeInstanceOf(z.ZodOptional);
-  expect(masked._zod.def.shape.field).toBeInstanceOf(z.ZodDefault);
-  expect(masked._zod.def.shape.country).toBeInstanceOf(z.ZodString);
-
-  masked.parse({ country: "US" });
-  await masked.parseAsync({ country: "US" });
-});
diff --git a/packages/zod/tests/pickomit-interface.test.ts b/packages/zod/tests/pickomit-interface.test.ts
deleted file mode 100644
index 0d7d3f85..00000000
--- a/packages/zod/tests/pickomit-interface.test.ts
+++ /dev/null
@@ -1,125 +0,0 @@
-import { expect, expectTypeOf, test } from "vitest";
-import * as z from "zod";
-
-const fish = z.interface({
-  name: z.string(),
-  age: z.number(),
-  nested: z.interface({}),
-});
-
-test("pick type inference", () => {
-  const nameonlyFish = fish.pick({ name: true });
-  type nameonlyFish = z.infer<typeof nameonlyFish>;
-  expectTypeOf<nameonlyFish>().toEqualTypeOf<{ name: string }>();
-});
-
-test("pick", () => {
-  fish.pick({ name: true }).parse({ name: "bob" });
-  fish.pick({ name: true }).parse({ name: "12" });
-  fish.pick({ name: true }).parse({ name: "bob", age: 12 });
-  fish.pick({ age: true }).parse({ age: 12 });
-
-  // @ts-expect-error checking runtime picks `name` only.
-  const b = fish.pick({ name: true, age: false });
-  b.parse({ name: "bob" });
-  b.parse({ name: "bob", age: 12 });
-  expect(() => b.parse({ age: 12 })).toThrow();
-});
-
-test("pick parse - fail", () => {
-  fish.pick({ name: true }).parse({ name: "12" } as any);
-  fish.pick({ name: true }).parse({ name: "bob", age: 12 } as any);
-  fish.pick({ age: true }).parse({ age: 12 } as any);
-
-  const nameonlyFish = fish.pick({ name: true }).strict();
-  const bad1 = () => nameonlyFish.parse({ name: 12 } as any);
-  const bad2 = () => nameonlyFish.parse({ name: "bob", age: 12 } as any);
-  const bad3 = () => nameonlyFish.parse({ age: 12 } as any);
-
-  // @ts-expect-error checking runtime picks `name` only.
-  const anotherNameonlyFish = fish.pick({ name: true, age: false }).strict();
-  const bad4 = () => anotherNameonlyFish.parse({ name: "bob", age: 12 } as any);
-
-  expect(bad1).toThrow();
-  expect(bad2).toThrow();
-  expect(bad3).toThrow();
-  expect(bad4).toThrow();
-});
-
-test("pick - remove optional", () => {
-  const schema = z.interface({ a: z.string, "b?": z.string() });
-  expect(schema.pick({ a: true })._zod.def.optional).toEqual([]);
-  expect(schema.pick({ b: true })._zod.def.optional).toEqual(["b"]);
-});
-
-test("omit type inference", () => {
-  const nonameFish = fish.omit({ name: true });
-  type nonameFish = z.infer<typeof nonameFish>;
-
-  expectTypeOf<nonameFish>().toEqualTypeOf<{ age: number; nested: object }>();
-});
-
-test("omit parse - success", () => {
-  const nonameFish = fish.omit({ name: true });
-  nonameFish.parse({ age: 12, nested: {} });
-
-  // @ts-expect-error checking runtime omits `name` only.
-  const anotherNonameFish = fish.omit({ name: true, age: false });
-  anotherNonameFish.parse({ age: 12, nested: {} });
-});
-
-test("omit parse - fail", () => {
-  const nonameFish = fish.omit({ name: true });
-  const bad1 = () => nonameFish.parse({ name: 12 } as any);
-  const bad2 = () => nonameFish.parse({ age: 12 } as any);
-  const bad3 = () => nonameFish.parse({} as any);
-
-  // @ts-expect-error checking runtime omits `name` only.
-  const anotherNonameFish = fish.omit({ name: true, age: false });
-  const bad4 = () => anotherNonameFish.parse({ nested: {} } as any);
-
-  expect(bad1).toThrow();
-  expect(bad2).toThrow();
-  expect(bad3).toThrow();
-  expect(bad4).toThrow();
-});
-
-test("omit - remove optional", () => {
-  const schema = z.interface({ a: z.string(), "b?": z.string() });
-  expect(schema.omit({ a: true })._zod.def.optional).toEqual(["b"]);
-  expect(schema.omit({ b: true })._zod.def.optional).toEqual([]);
-});
-
-test("nonstrict inference", () => {
-  const laxfish = fish.pick({ name: true }).catchall(z.any());
-  type laxfish = z.infer<typeof laxfish>;
-  expectTypeOf<laxfish>().toEqualTypeOf<{ name: string; [k: string]: any }>();
-});
-
-test("nonstrict parsing - pass", () => {
-  const laxfish = fish.loose().pick({ name: true });
-  laxfish.parse({ name: "asdf", whatever: "asdf" });
-  laxfish.parse({ name: "asdf", age: 12, nested: {} });
-});
-
-test("nonstrict parsing - fail", () => {
-  const laxfish = fish.loose().pick({ name: true });
-  const bad = () => laxfish.parse({ whatever: "asdf" } as any);
-  expect(bad).toThrow();
-});
-
-test("pick/omit/required/partial - do not allow unknown keys", () => {
-  const schema = z.interface({
-    name: z.string(),
-    age: z.number(),
-  });
-
-  // @ts-expect-error
-  expect(() => schema.pick({ $unknown: true })).toThrow();
-  // @ts-expect-error
-  expect(() => schema.omit({ $unknown: true })).toThrow();
-  // @ts-expect-error
-  expect(() => schema.required({ $unknown: true })).toThrow();
-  // @ts-expect-error
-  expect(() => schema.partial({ $unknown: true })).toThrow();
-});
diff --git a/packages/zod/tests/pickomit-object.test.ts b/packages/zod/tests/pickomit-object.test.ts
index 1b20f284..7d0cbfe1 100644
--- a/packages/zod/tests/pickomit-object.test.ts
+++ b/packages/zod/tests/pickomit-object.test.ts
@@ -43,9 +43,12 @@ test("pick parse - fail", () => {
 });
 
 test("pick - remove optional", () => {
-  const schema = z.interface({ a: z.string, "b?": z.string() });
-  expect(schema.pick({ a: true })._zod.def.optional).toEqual([]);
-  expect(schema.pick({ b: true })._zod.def.optional).toEqual(["b"]);
+  const schema = z.object({ a: z.string(), b: z.string().optional() });
+  expect(schema._zod.def.shape.a._zod.optionality).toEqual(undefined);
+  expect(schema._zod.def.shape.b!._zod.optionality).toEqual("optional");
+  const picked = schema.pick({ a: true });
+  expect(picked._zod.def.shape.a._zod.optionality).toEqual(undefined);
+  expect("b" in picked._zod.def.shape!).toEqual(false);
 });
 
 test("omit type inference", () => {
@@ -81,9 +84,10 @@ test("omit parse - fail", () => {
 });
 
 test("omit - remove optional", () => {
-  const schema = z.interface({ a: z.string, "b?": z.string() });
-  expect(schema.omit({ a: true })._zod.def.optional).toEqual(["b"]);
-  expect(schema.omit({ b: true })._zod.def.optional).toEqual([]);
+  const schema = z.object({ a: z.string(), b: z.string().optional() });
+  const omitted = schema.omit({ a: true });
+  expect("a" in omitted._zod.def.shape).toEqual(false);
+  expect(omitted._zod.def.shape.b!._zod.optionality).toEqual("optional");
 });
 
 test("nonstrict inference", () => {
diff --git a/packages/zod/tests/recursive-object.test.ts b/packages/zod/tests/recursive-object.test.ts
deleted file mode 100644
index 22def211..00000000
--- a/packages/zod/tests/recursive-object.test.ts
+++ /dev/null
@@ -1,134 +0,0 @@
-import { expect, test } from "vitest";
-
-import { z } from "zod";
-
-test("schema getter", () => {
-  z.lazy(() => z.string()).parse("asdf");
-});
-
-test("lazy proxy", () => {
-  const schema = z.lazy(() => z.string())._zod._getter.min(6);
-  schema.parse("123456");
-  expect(schema.safeParse("12345").success).toBe(false);
-});
-
-interface Category {
-  name: string;
-  subcategories: Category[];
-}
-
-const testCategory: Category = {
-  name: "I",
-  subcategories: [
-    {
-      name: "A",
-      subcategories: [
-        {
-          name: "1",
-          subcategories: [
-            {
-              name: "a",
-              subcategories: [],
-            },
-          ],
-        },
-      ],
-    },
-  ],
-};
-
-test("recursion with z.lazy", () => {
-  const Category: z.ZodType<Category> = z.lazy(() =>
-    z.object({
-      name: z.string(),
-      subcategories: z.array(Category),
-    })
-  );
-  Category.parse(testCategory);
-});
-
-type LinkedList = null | { value: number; next: LinkedList };
-
-const linkedListExample = {
-  value: 1,
-  next: {
-    value: 2,
-    next: {
-      value: 3,
-      next: {
-        value: 4,
-        next: null,
-      },
-    },
-  },
-};
-
-test("recursion involving union type", () => {
-  const LinkedListSchema: z.ZodType<LinkedList> = z.lazy(() =>
-    z.union([
-      z.null(),
-      z.object({
-        value: z.number(),
-        next: LinkedListSchema,
-      }),
-    ])
-  );
-  LinkedListSchema.parse(linkedListExample);
-});
-
-interface A {
-  val: number;
-  b: B;
-}
-
-interface B {
-  val: number;
-  a?: A | undefined;
-}
-
-const Alazy: z.ZodType<A> = z.lazy(() =>
-  z.object({
-    val: z.number(),
-    b: Blazy,
-  })
-);
-
-const Blazy: z.ZodType<B> = z.lazy(() =>
-  z.object({
-    val: z.number(),
-    a: Alazy.optional(),
-  })
-);
-
-test("mutual recursion", () => {
-  const testData = {
-    val: 1,
-    b: {
-      val: 5,
-      a: {
-        val: 3,
-        b: {
-          val: 4,
-          a: {
-            val: 2,
-            b: {
-              val: 1,
-            },
-          },
-        },
-      },
-    },
-  };
-
-  Alazy.parse(testData);
-  Blazy.parse(testData.b);
-
-  expect(() => Alazy.parse({ val: "asdf" })).toThrow();
-});
-
-test("mutual recursion with cyclical data", () => {
-  const a: any = { val: 1 };
-  const b: any = { val: 2 };
-  a.b = b;
-  b.a = a;
-});
diff --git a/packages/zod/tests/recursive-interface.test.ts b/packages/zod/tests/recursive-types.test.ts
similarity index 73%
rename from packages/zod/tests/recursive-interface.test.ts
rename to packages/zod/tests/recursive-types.test.ts
index 290c2fb8..5079e46f 100644
--- a/packages/zod/tests/recursive-interface.test.ts
+++ b/packages/zod/tests/recursive-types.test.ts
@@ -1,5 +1,4 @@
 import { expect, expectTypeOf, test } from "vitest";
-
 import { z } from "zod";
 
 test("recursion with z.lazy", () => {
@@ -23,7 +22,7 @@ test("recursion with z.lazy", () => {
     ],
   };
 
-  const Category = z.interface({
+  const Category = z.object({
     name: z.string(),
     get subcategories() {
       return z.array(Category);
@@ -47,34 +46,32 @@ test("recursion involving union type", () => {
     },
   };
 
-  const LinkedListSchema = z.union([
-    z.null(),
-    z.interface({
+  const LL = z
+    .object({
       value: z.number(),
       get next() {
-        return LinkedListSchema;
+        return LL.nullable();
       },
-    }),
-  ]);
-
-  LinkedListSchema.parse(data);
-});
+    })
+    .or(z.null());
 
-const Alazy = z.interface({
-  val: z.number(),
-  get b() {
-    return Blazy;
-  },
+  LL.parse(data);
 });
 
-const Blazy = z.interface({
-  val: z.number(),
-  get a() {
-    return Alazy.optional();
-  },
-});
+test("mutual recursion - native", () => {
+  const Alazy = z.object({
+    val: z.number(),
+    get b() {
+      return Blazy;
+    },
+  });
 
-test("mutual recursion", () => {
+  const Blazy = z.object({
+    val: z.number(),
+    get a() {
+      return Alazy.optional();
+    },
+  });
   const testData = {
     val: 1,
     b: {
@@ -100,18 +97,8 @@ test("mutual recursion", () => {
   expect(() => Alazy.parse({ val: "asdf" })).toThrow();
 });
 
-// test("mutual recursion with cyclical data", () => {
-//   const a: any = { val: 1 };
-//   const b: any = { val: 2 };
-//   a.b = b;
-//   b.a = a;
-
-//   Alazy.parse(a);
-//   Blazy.parse(b);
-// });
-
-test("pick and omit with recursive interface", () => {
-  const Category = z.strictInterface({
+test("pick and omit with getter", () => {
+  const Category = z.strictObject({
     name: z.string(),
     get subcategories() {
       return z.array(Category);