ianstormtaylor / superstruct

A simple and composable way to validate data in JavaScript (and TypeScript).
https://docs.superstructjs.org
MIT License
6.96k stars 223 forks source link

Added code to enable type printing #1209

Open only-cliches opened 8 months ago

only-cliches commented 8 months ago

Hello,

I have a use case where I'd like to be able to export a string containing the Typescript types for a given Superstruct.

This kinda works, many of the types have a schema property in the Struct class that can be inspected to print the internal types.

However, there are quite a few types where this just isn't possible at the moment. For example: map, set, and instance types do not pass the nested type into the schema property of the Struct class, so this data isn't available after the type is created.

Additionally, type modifiers like optional, nullable, and default do not pass any information onto the Struct class, making it impossible to inspect the presence of these modifiers.

To give you an idea of what I'm trying to accomplish, here is the current code that is only partially working:

const printTS = (struct: Struct): string => {
    switch (struct.type) {
        case "array":
            return `(${printTS(struct.schema as any)})[]`
        case "enums":
            return "[" + (struct.schema as any[]).map(printTS).join(", ") + "]";
        case "union":
            return (struct.schema as any[]).map(printTS).join(" | ")
        case "literal":
            return `${struct.schema} as const`
        case "integer":
            return "number";
        case "func":
            return "(...args: any) => any"
        case "date":
            return "Date";
        case "bigint":
            return "BigInt";
        case "regexp":
            return "RegExp";
        case "number":
        case "any":
        case "never":
        case "boolean":
        case "string":
        case "unknown":
            return struct.type;
        case "object":
        case "type":
            return "{" +  Object.keys(struct.schema as any).map(s => `${s}: ${printTS((struct.schema as any)[s])}`).join(",") + "}";
        case "map": // impossible
        case "intersection": // impossible
        case "set": // impossible
        case "tuple": // impossible
        case "instance": // impossible
        break;
    }
    return ""
}

This pull request makes the minimal necessary changes to complete the function above and get it working for all types.