Skip to content

Conversation

@srsudar
Copy link
Contributor

@srsudar srsudar commented Nov 23, 2025

Overview

The tool currently supports either generating types for all exported types (which you get by not passing the type or passing '*'). There is no way currently to emit only a list of named types. So you wind up with either a single type or every exported type. This is requested in #1223.

This PR adds a --types property that accepts an array of type names. This lets you generate a list of types.

In this implementation, types wind up at the top-level even if they are referenced but not listed in the types array. So this, eg:

type NonExportedType = {
    misc: number;
};

export type ExportedType = {
    val: string;
    val2: NonExportedType;
};

export interface ExportedInterface {
    val: string;
}

// Exported, so we include it as a root node
export type Object1Prop = {
    name: string;
};

type Object2Prop = {
    description: string;
};

export type MyObject1 = {
    id: number;
    bar: Object1Prop;
};

export type MyObject2 = {
    idStr: string;
    baz: Object2Prop;
};

With invoked as --types=MyObject1,MyObject2 will include to-level types for MyObject1, MyObject2, AND Object1Prop. Object2Prop will be inlined.

Version

Published prerelease version: v2.5.0-next.8

Changelog

🎉 This release contains work from new contributors! 🎉

Thanks for all your work!

❤️ Sam Sudar (@srsudar)

❤️ Orta Therox (@orta)

❤️ James Vaughan (@jamesbvaughan)

❤️ Alex (@alexchexes)

❤️ Cal (@CalLavicka)

❤️ Valentyne Stigloher (@pixunil)

🚀 Enhancement

🐛 Bug Fix

🔩 Dependency Updates

Authors: 9

@srsudar
Copy link
Contributor Author

srsudar commented Nov 23, 2025

@domoritz , what do you think of this?

I haven't yet run it locally outside of tests, so I'm not sure if it's hooked up to the CLI etc.

@srsudar
Copy link
Contributor Author

srsudar commented Nov 23, 2025

Also, it should probably throw if you try to pass both type and types.

Copy link
Member

@domoritz domoritz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's great. Should we simplify the internal apis to only accept types and then once at the beginning convert to a list of the user provides type via the api?

@srsudar
Copy link
Contributor Author

srsudar commented Nov 24, 2025

What is the process I should use for running my version locally? I want to convince myself it works.

@domoritz
Copy link
Member

Test and cli can run locally. See readme for instructions.

* Use "*" to generate schemas for all exported types.
*/
type?: string;
type?: string | string[];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not positive this is the right way to type this.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks reasonable

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because of how you set a (value: string, previous: string[] | undefined) mapper, wouldn't type always be an array? Most likely an array with a single item inside?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If so, i think you can simplify the code by removing the castArray and letting all related types be a single array[] (Also remove undefined support and just check for types.length === 0.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If not, cast it into an array at the createGenerator(config).createSchema(config.type) level.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if I'm misunderstanding what you guys are asking.

I thought that this Config object was defining valid inputs for the library, so that by type?: string | string[], we were saying that programmatic usage accepts undefined, a single string, or an array of string.

And I thought the (value: string, previous: string[] | undefined) mapper was only applying when invoked via the CLI. If --type is not passed on the CLI, the final value is undefined (b/c the mapper is never invoked). If one or more values are passed, then mapper is invoked and it will always be an array, even with just a single item.

So I think if Config.type was changed to an array, I think it would be a breaking change.

I have a PR making this change here against an older version of this branch:

https://github.com/srsudar/ts-json-schema-generator/pull/1/files#diff-b83e1482492860acb73eb6a72535d0dd31b4fc971525ff13c35fb97222172d39

Am I misunderstanding something? Is that version basically the change you're asking for? Happy to do it if so!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think supporting both and just using the default is easier. I'll make the change.

@srsudar
Copy link
Contributor Author

srsudar commented Nov 24, 2025

Test and cli can run locally. See readme for instructions.

Tests are passing locally, and using the CLI locally seemed to do what I wanted it to do.

.option(
"-t, --type <name>",
"Type name (can be passed multiple times)",
(value: string, previous: string[] | undefined) => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if it will always return an array, then the typings can be a simple string[]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My thinking here was that previous can be undefined, since I'm not passing a default arg.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we use ... instead as documented in https://github.com/tj/commander.js?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My understanding (and this is just from reading the docs and talking to chatgpt--I don't have any real experience with commander), was that ... allows for --type Foo Bar rather than --type Foo --type Bar, as Arthur asked for (and that I guess is more common, at least according to the LLMs). There were also some parsing ambiguities around variadic arguments that seemed to trip people up when I googled.

Although I see now that one of their examples does show both working:

$ collect --letter -n 1 -n 2 3 -- operand
Options:  { number: [ '1', '2', '3' ], letter: true }
Remaining arguments:  [ 'operand' ]

They have a section in the docs about ambiguity in parsing variadic arguments that I didn't think applied to the collect approach I took here.

Let me know if you'd prefer I switch to variadic arguments.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like his approach of always returning an array :)

Copy link
Member

@domoritz domoritz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good once the last comment is resolved.

@domoritz domoritz enabled auto-merge (squash) November 28, 2025 21:10
@domoritz
Copy link
Member

Could you fix the lint error so we can merge?

auto-merge was automatically disabled November 28, 2025 22:56

Head branch was pushed to by a user without write access

@srsudar
Copy link
Contributor Author

srsudar commented Nov 28, 2025

Could you fix the lint error so we can merge?

Done, I think. npm run lint passes locally.

@srsudar
Copy link
Contributor Author

srsudar commented Nov 29, 2025

Could you fix the lint error so we can merge?

Done, I think. npm run lint passes locally.

Added a test to try and get the patch coverage to pass. I think the only line that I added that wasn't tested was throwing for mixed types, like type: ["*", "Foo"].

.option(
"-t, --type <name>",
"Type name (can be passed multiple times)",
(value: string, previous: string[] | undefined) => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like his approach of always returning an array :)

* Use "*" to generate schemas for all exported types.
*/
type?: string;
type?: string | string[];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because of how you set a (value: string, previous: string[] | undefined) mapper, wouldn't type always be an array? Most likely an array with a single item inside?

* Use "*" to generate schemas for all exported types.
*/
type?: string;
type?: string | string[];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If so, i think you can simplify the code by removing the castArray and letting all related types be a single array[] (Also remove undefined support and just check for types.length === 0.

* Use "*" to generate schemas for all exported types.
*/
type?: string;
type?: string | string[];
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If not, cast it into an array at the createGenerator(config).createSchema(config.type) level.

@domoritz domoritz merged commit ce1a670 into vega:next Nov 30, 2025
4 checks passed
@github-actions
Copy link

🚀 PR was released in v2.5.0-next.8 🚀

@domoritz
Copy link
Member

We need string | string[] for backwards compatibility.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants