Steps to reproduce
Create these two dependency-free files.
warmup.ts
type SomeJSONSchema = UncheckedJSONSchemaType<Known, true>
type JSONType<T extends string, Partial extends boolean> =
Partial extends true ? T | undefined : T
type UncheckedJSONSchemaType<T, Partial extends boolean> = (
| { anyOf: readonly UncheckedJSONSchemaType<T, Partial>[] }
| (T extends string
? { type: JSONType<"string", Partial> }
: T extends readonly any[]
? {
type: JSONType<"array", Partial>
items: UncheckedJSONSchemaType<T[0], false>
}
: T extends Record<string, any>
? {
type: JSONType<"object", Partial>
properties?: Partial extends true
? Partial<UncheckedPropertiesSchema<T>>
: UncheckedPropertiesSchema<T>
required: readonly (keyof T)[]
}
: never)
) & { [keyword: string]: any }
type JSONSchemaType<T> = UncheckedJSONSchemaType<T, false>
type Known = { [key: string]: Known } | Known[] | string
type UncheckedPropertiesSchema<T> = {
[K in keyof T]-?: UncheckedJSONSchemaType<T[K], false> & Nullable<T[K]>
}
type Nullable<T> = {
enum?: readonly T[]
}
interface CompletionParameters {
responseFormat?:
| { type: "json_object" }
| {
type: "json_schema"
json_schema: { schema?: SomeJSONSchema }
}
}
interface Item {
value: string
}
const itemSchema: JSONSchemaType<Item> = {
type: "object",
properties: { value: { type: "string" } },
required: ["value"],
}
interface WarmResult {
items: Item[]
}
const warmResultSchema: JSONSchemaType<WarmResult> = {
type: "object",
properties: {
items: { type: "array", items: itemSchema },
},
required: ["items"],
}
target.ts
interface Result {
items: Item[]
}
const resultSchema: JSONSchemaType<Result> = {
type: "object",
properties: {
items: { type: "array", items: itemSchema },
},
required: ["items"],
}
class TargetPrompt {
completionParameters: CompletionParameters = {
responseFormat: {
type: "json_schema",
json_schema: { schema: resultSchema },
},
}
}
Versions tested:
- TypeScript 6.0.3
- tsgo 7.0.2, git commit
2bd066d87f5bafd315be9f40889d0a60b9e58e0b
Run the files in this order:
- ❌
tsc --ignoreConfig --strict --noEmit --pretty false warmup.ts target.ts
- ✅
tsgo --ignoreConfig --strict --noEmit --pretty false warmup.ts target.ts
Reversing the root-file order makes both compilers accept the program:
- ✅
tsc --ignoreConfig --strict --noEmit --pretty false target.ts warmup.ts
- ✅
tsgo --ignoreConfig --strict --noEmit --pretty false target.ts warmup.ts
Behavior with typescript@6.0
The warmup-first command exits with code 2:
target.ts(17,22): error TS2322: Type 'JSONSchemaType<Result>' is not assignable to type 'SomeJSONSchema | undefined'.
Type '{ anyOf: readonly UncheckedJSONSchemaType<Result, false>[] } & { [keyword: string]: any }' is not assignable to type 'SomeJSONSchema | undefined'.
Behavior with tsgo
The same warmup-first command exits successfully with no diagnostics.
Expected behavior
tsgo should report the same assignability error as TypeScript 6 for the same root-file order.
warmResultSchema is unrelated to and unused by TargetPrompt. Its presence and root-file position should not change whether resultSchema is assignable to SomeJSONSchema.
The types are minimized from AJV’s recursive JSONSchemaType<T> and SomeJSONSchema types. AJV documents that these widened types are incompatible in ajv-validator/ajv#1988, so tsgo’s successful result appears to be a false negative. This may relate to recursive relation caching or bailout order.
Steps to reproduce
Create these two dependency-free files.
warmup.tstarget.tsVersions tested:
2bd066d87f5bafd315be9f40889d0a60b9e58e0bRun the files in this order:
tsc --ignoreConfig --strict --noEmit --pretty false warmup.ts target.tstsgo --ignoreConfig --strict --noEmit --pretty false warmup.ts target.tsReversing the root-file order makes both compilers accept the program:
tsc --ignoreConfig --strict --noEmit --pretty false target.ts warmup.tstsgo --ignoreConfig --strict --noEmit --pretty false target.ts warmup.tsBehavior with
typescript@6.0The warmup-first command exits with code 2:
Behavior with
tsgoThe same warmup-first command exits successfully with no diagnostics.
Expected behavior
tsgo should report the same assignability error as TypeScript 6 for the same root-file order.
warmResultSchemais unrelated to and unused byTargetPrompt. Its presence and root-file position should not change whetherresultSchemais assignable toSomeJSONSchema.The types are minimized from AJV’s recursive
JSONSchemaType<T>andSomeJSONSchematypes. AJV documents that these widened types are incompatible in ajv-validator/ajv#1988, so tsgo’s successful result appears to be a false negative. This may relate to recursive relation caching or bailout order.