Skip to content

Commit

Permalink
wip: recursively infer parser return type
Browse files Browse the repository at this point in the history
  • Loading branch information
beenotung committed Oct 30, 2023
1 parent 1d8e50e commit 9b4036d
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 7 deletions.
7 changes: 5 additions & 2 deletions examples/infer-demo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ console.log(parser.type)

type Result = ParseResult<typeof parser>
type Post = Result['postList'][number]
// @ts-expect-error
type PostStatus = Post['status']

// TODO extract object field name without $suffix
function checkType<T>(t: T) {
/* noop */
}

checkType<'active' | 'hidden'>(null as unknown as PostStatus)
13 changes: 12 additions & 1 deletion src/core.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ describe('object parser', () => {
}`)
}
})
it('should infer result type without $ flags', () => {
it('should infer result type without enums/nullable/optional flags', () => {
let parser = inferFromSampleValue({
'status_1$enums': ['a' as const, 'b' as const],
'status_2$enum': ['a' as const, 'b' as const],
Expand Down Expand Up @@ -500,6 +500,17 @@ describe('object parser', () => {
status_11?: undefined | null | 'a' | 'b'
}>(result)
})
it('should recursively infer result type', () => {
let parser = inferFromSampleValue({
a$nullable: {
b$optional: {
c$enums: ['a' as const, 'b' as const],
},
},
})
let result = parser.parse({ a: { b: { c: 'a' } } })
expect(result.a?.b?.c).to.equals('a')
})
})

describe('date parser', () => {
Expand Down
8 changes: 4 additions & 4 deletions src/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1097,27 +1097,27 @@ type InferNullableField<O> = {
? never
: P extends `${string}$null${string}`
? never
: P]: O[P]
: P]: InferType<O[P]>
} & {
[P in keyof O as P extends `${infer H}$nullable${infer T}`
? `${H}${T}`
: P extends `${infer H}$null${infer T}`
? `${H}${T}`
: never]: null | O[P]
: never]: null | InferType<O[P]>
}

type InferOptionalField<O> = {
[P in keyof O as P extends `${string}$optional${string}`
? never
: P extends `${string}?${string}`
? never
: P]: O[P]
: P]: InferType<O[P]>
} & {
[P in keyof O as P extends `${infer H}$optional${infer T}`
? `${H}${T}`
: P extends `${infer H}?${infer T}`
? `${H}${T}`
: never]?: O[P]
: never]?: InferType<O[P]>
}

type InferObjectType<T> = InferOptionalField<
Expand Down

0 comments on commit 9b4036d

Please sign in to comment.