Skip to content

Commit

Permalink
feat: preserve JSDoc comments attached to required properties (#837)
Browse files Browse the repository at this point in the history
  • Loading branch information
Dimava authored Aug 4, 2023
1 parent cef5dac commit 8eeadfb
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 8 deletions.
5 changes: 5 additions & 0 deletions dev/configs/.changeset/keep-jsdoc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"arktype": patch
---

Make types keep JSDoc for required keys
64 changes: 64 additions & 0 deletions dev/test/jsdoc.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { describe, it } from "mocha"
import { scope, type } from "../../src/main.js"

const ab = { a: "1", b: 1 }
describe("JSDoc", () => {
// Note: `<#` are not checked, they are for understandability
it("objects keep JSDoc", () => {
type({
/** JSDoc */
a: "string"
}).assert(ab).a // <# JSDoc
})
it("intersections keep JSDoc", () => {
type([
{
/** JSDoc */
a: "string"
},
"&",
{
b: "number"
}
]).assert(ab).a // <# JSDoc

type([
{
/** First */
a: "string"
},
"&",
{
/** Second */
a: "string"
}
]).assert(ab).a // <# First

scope({
a: {
/** JSDoc */
a: "string"
},
b: {
b: "number"
},
ab: "a & b"
})
.compile()
.ab.assert(ab).a // <# JSDoc
})

it("works with module scopes", () => {
scope({
/** JSDoc */
a: "string"
}).compile().a // <# JSDoc
})

it("doesn't work with optional keys", () => {
type({
/** JSDoc */
"a?": "string"
}).assert(ab).a // <# ---
})
})
11 changes: 7 additions & 4 deletions src/parse/ast/intersection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import type {
extractValues,
isAny,
List,
stringKeyOf,
tryCatch
} from "../../utils/generics.js"
import { objectKeysOf } from "../../utils/generics.js"
Expand Down Expand Up @@ -42,9 +41,13 @@ type inferIntersectionRecurse<
? bubblePropErrors<
evaluate<
{
[k in stringKeyOf<l>]: k extends keyof r
? inferIntersectionRecurse<l[k], r[k], [...path, k]>
: l[k]
[k in keyof l as k extends string
? k
: never]: k extends string
? k extends keyof r
? inferIntersectionRecurse<l[k], r[k], [...path, k]>
: l[k]
: never
} & Omit<r, keyof l>
>
>
Expand Down
11 changes: 9 additions & 2 deletions src/parse/ast/union.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type {
error,
extractValues,
isAny,
optionalKeyOf,
requiredKeyOf
} from "../../utils/generics.js"
import type { objectKindOf } from "../../utils/objectKinds.js"
Expand Down Expand Up @@ -42,8 +43,14 @@ type discriminatableRecurse<
: [objectKindOf<l>, objectKindOf<r>] extends ["Object", "Object"]
? extractValues<
{
[k in requiredKeyOf<l>]: k extends requiredKeyOf<r>
? discriminatableRecurse<l[k], r[k], [...path, k & string]>
[k in keyof l as k extends optionalKeyOf<l>
? never
: k]: k extends requiredKeyOf<r>
? discriminatableRecurse<
l[k],
r[k],
[...path, k & string]
> & { _: l }
: never
},
string[]
Expand Down
11 changes: 9 additions & 2 deletions src/parse/record.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,15 @@ type withPossiblePreviousEscapeCharacter<k> = k extends `${infer name}?`

export type inferRecord<def extends Dict, $> = evaluate<
{
[requiredKeyName in requiredKeyOf<def>]: inferDefinition<
def[withPossiblePreviousEscapeCharacter<requiredKeyName>],
[k in keyof def as k extends requiredKeyOf<def>
? k
: never]: inferDefinition<
def[withPossiblePreviousEscapeCharacter<k>],
$
>
} & {
[k in Exclude<requiredKeyOf<def>, keyof def>]: inferDefinition<
def[withPossiblePreviousEscapeCharacter<k>],
$
>
} & {
Expand Down

0 comments on commit 8eeadfb

Please sign in to comment.