skip to Main Content

Suppose I have the schema in javascript:

import {z} from "zod";
let personSchema = z.object({
  name: z.string(),
  id: z.number()
});

now I want to use the type somewhere else:

/** 
* @param {{name:string, id:number}} person 
* but should instead be something like this?:
* @param {???(typeof z)["infer"]<typeof personSchema>???} person 
*/
function (person) {
 person.name; // autocompletions and vscode linting should work here
 // do stuff
}

Of course this would be easy in typescript, but I’m trying to use JSDOC since the project doesn’t allow TypeScript.

2

Answers


  1. Chosen as BEST ANSWER

    This works:

    /** 
    * @param {ReturnType<(typeof personSchema)["parse"]>} person
    */ 
    function (person) {
     person.name; // autocompletions and vscode linting should work here
     // do stuff
    }
    

    Although this works, I suspect there is a better solution.


  2. One thing you could try is to take advantage of the separation between the type namespace and the values namespace by exporting the type of the schema with the same name as the schema. For example you could say

    export const personSchema = z.object({ /* ... */ });
    // If you're using eslint, it may complain here but you can ignore
    // the redeclaration complaint
    export type personSchema = z.infer<typeof personSchema>;
    

    When Typescript is working out the types from the JSDOC the personSchema type will be imported and will resolve so you get the correct value with:

    /**
     * @param {personSchema} person
     */
    function (person) {
      person.name;
    };
    

    This will work with regular JS since the types won’t exist so only the schema will be imported, and it will also work with TS because it can distinguish between something being used as a type and something that is a value.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search