Skip to content

Commit

Permalink
feat: Support Record<T, U> (#161)
Browse files Browse the repository at this point in the history
* chore: update eslint

* feat: support Record<T, U>
  • Loading branch information
fabien0102 committed Oct 17, 2023
1 parent 8d3b297 commit ac24784
Show file tree
Hide file tree
Showing 4 changed files with 298 additions and 187 deletions.
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -75,7 +75,7 @@
"auto-changelog": "^2.2.1",
"babel-jest": "^27.5.1",
"codecov": "^3.8.3",
"eslint": "^7.22.0",
"eslint": "^8.51.0",
"eslint-config-prettier": "^8.1.0",
"eslint-plugin-prettier": "^3.3.1",
"husky": "^5.2.0",
Expand Down
17 changes: 10 additions & 7 deletions src/core/generateZodSchema.test.ts
Expand Up @@ -291,13 +291,6 @@ describe("generateZodSchema", () => {
);
});

it("should throw on non string record", () => {
const source = `export type UnsupportedType = Record<number, number>;`;
expect(() => generate(source)).toThrowErrorMatchingInlineSnapshot(
`"Record<number, …> are not supported (https://github.com/colinhacks/zod/tree/v3#records)"`
);
});

it("should throw on not supported key in omit", () => {
const source = `export type UnsupportedType = Omit<Superman, Krytonite>;`;
expect(() => generate(source)).toThrowErrorMatchingInlineSnapshot(
Expand Down Expand Up @@ -540,6 +533,16 @@ describe("generateZodSchema", () => {
);
});

it("should deal with record with a union as key", () => {
const source = `
export type AvailablePower = Record<Power, boolean>;
`;

expect(generate(source)).toMatchInlineSnapshot(
`"export const availablePowerSchema = z.record(powerSchema, z.boolean());"`
);
});

it("should deal with index access type (tuple)", () => {
const source = `export type SupermanPower = Superman["powers"][1];
Expand Down
40 changes: 32 additions & 8 deletions src/core/generateZodSchema.ts
Expand Up @@ -353,20 +353,44 @@ function buildZodPrimitive({

// Deal with `Record<>` syntax
if (identifierName === "Record" && typeNode.typeArguments) {
if (
typeNode.typeArguments.length !== 2 ||
typeNode.typeArguments[0].kind !== ts.SyntaxKind.StringKeyword
) {
throw new Error(
`Record<${typeNode.typeArguments[0].getText(
sourceFile
)}, …> are not supported (https://github.com/colinhacks/zod/tree/v3#records)`
if (typeNode.typeArguments[0].kind === ts.SyntaxKind.StringKeyword) {
// Short version (`z.record(zodType)`)
return buildZodSchema(
z,
"record",
[
buildZodPrimitive({
z,
typeNode: typeNode.typeArguments[1],
isOptional: false,
jsDocTags,
sourceFile,
isPartial: false,
dependencies,
getDependencyName,
skipParseJSDoc,
}),
],
zodProperties
);
}

// Expanded version (`z.record(zodType, zodType)`)
return buildZodSchema(
z,
"record",
[
buildZodPrimitive({
z,
typeNode: typeNode.typeArguments[0],
isOptional: false,
jsDocTags,
sourceFile,
isPartial: false,
dependencies,
getDependencyName,
skipParseJSDoc,
}),
buildZodPrimitive({
z,
typeNode: typeNode.typeArguments[1],
Expand Down

0 comments on commit ac24784

Please sign in to comment.