Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is there way to add typing to .meta()? #1

Closed
kozubsky opened this issue Apr 24, 2023 · 2 comments
Closed

Is there way to add typing to .meta()? #1

kozubsky opened this issue Apr 24, 2023 · 2 comments

Comments

@kozubsky
Copy link

kozubsky commented Apr 24, 2023

Hello, nice approach, few weeks ago I implemented someting similiar but there is no reason to duplicate similiar packages. And I really confused why zod author won't support this feature natively, however I understand his arguments.

Now I think about the way to make this lib support typing of data containing in meta. I tried to override default type Record<string, unknown> it in standalone d.ts but this unfortunately does not work (this only works when I edit embedded node_modules/zod-metadata/dist/index.d.ts):

type TMeta = {
    example?: any;
    description?: string;
}

declare module 'zod' {
    interface ZodTypeDef {
        meta?: TMeta;
    }
    interface ZodType {
        getMeta(): TMeta;
        meta(meta: TMeta): this;
    }
}

What do you thing about making at least optionally generic getMeta and meta methods, like this?

declare module 'zod' {
    interface ZodTypeDef {
        meta?: Record<string, unknown>;
    }
    interface ZodType {
        getMeta<T = Record<string, unknown>>(): T;
        meta<T = Record<string, unknown>>(meta: T): this;
    }
}

This is ugly, of course, but I really don't see other options to override meta typing. Maybe you have some ideas?

UPD: I solved overriding issue: first line import z from 'zod'; is neccessary to make it work, so we have a typed meta now! )

<root>/typings/zod-metadata.d.ts:

import z from 'zod';

declare module 'zod' {
    interface TMeta {
        one?: string;
        two?: number;
    }
}

And to make it work we need to slightly change node_modules/zod-metadata/dist/index.d.ts:

declare module 'zod' {
    interface TMeta {
        [k: string]: unknown;
    }
    interface ZodTypeDef {
        meta?: TMeta;
    }
    interface ZodType {
        getMeta(): TMeta;
        meta(meta: TMeta): this;
    }
}

This works because interfaces in TS can be extended, so we exactly extending TMeta.

@IvanovES IvanovES mentioned this issue Apr 24, 2023
4 tasks
@IvanovES
Copy link
Owner

@kozubsky hey, thanks for the issue. I'll give it a shot. Can you check if #2 does it?

@kozubsky
Copy link
Author

kozubsky commented Apr 25, 2023

@kozubsky hey, thanks for the issue. I'll give it a shot. Can you check if #2 does it?

Hello, thank you for your attention to this issue! I tried both approaches and the original one works better for my purposes. Let me explain.

(A) Defining global type for all meta() and getMeta() calls. It supports autocomplete (at least in JetBrains' IDE).

node_modules/zod-metadata/dist/index.d.ts

import z from 'zod';

declare module 'zod' {
    interface TMeta {
        [k: string]: unknown;
    }
    interface ZodTypeDef {
        meta?: TMeta;
    }
    interface ZodType {
        getMeta(): TMeta;
        meta(meta: TMeta): this;
    }
}

export declare function register(zod: typeof z): void;

And overriding TMeta interface in project, for example in <root>/typings/zod-metadata.d.ts:

import z from 'zod';

declare module 'zod' {
    interface TMeta {
        name: string;
        age?: number;
    }
}

Finally, we have this:

image

image

(B) Approach from #2 automagically infers type from meta() argument and it works... Within single file. In another file IDE has no idea about getMeta() return type anymore, unfortunately.

Please consider this pull request #3 with updated documentation and examples.

@IvanovES IvanovES closed this as not planned Won't fix, can't repro, duplicate, stale Jun 13, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants