glideapps / quicktype

Generate types and converters from JSON, Schema, and GraphQL
https://app.quicktype.io
Apache License 2.0
12.12k stars 1.06k forks source link

Typescript zod (and effect) language uses block scoped variables before they've been declared #2414

Closed kriswest closed 7 months ago

kriswest commented 11 months ago

While attempting to generate zod schemas from a fairly large set of JSON Schemas we've noted multiple places where a block-scoped variable representing one of the schemas is used before its been declared, meaning the source file generated is unusable

export const RaiseIntentResultBridgeResponsePayloadSchema = z.object({
    "intentResult": IntentResultSchema,
});

...

export const IntentResultSchema = z.object({
    "context": z.union([ContextElementSchema, z.null()]).optional(),
    "channel": z.union([ChannelSchema, z.null()]).optional(),
});

The same happens in the Typescript generator, but it doesn't matter there as the interfaces aren't variables

 * The message payload typically contains return values for FDC3 API functions.
 */
export interface RaiseIntentResultAgentResponsePayload {
  intentResult: IntentResult;
}

...

export interface IntentResult {
  context?: ContextElement;
  channel?: Channel;
}

Presumably, this occurs due to a logical error in this code: https://github.com/glideapps/quicktype/blob/9b570a73a896306778940c793c0037a38815304a/packages/quicktype-core/src/language/TypeScriptZod.ts#L201-L228

I assume the issue also affects the TypeScript effect schema language as it uses the same code.

@ryoid @Southclaws @dvdsgl

kriswest commented 11 months ago

I instrumented the above code and determined that it outputs in the same order as the input as the comparison mapKey[depIndex] === depName is never true.