[GH-ISSUE #1004] Create or document how to use a TypeScript type for configuration schema #591

Closed
opened 2026-03-03 01:28:17 +03:00 by kerem · 4 comments
Owner

Originally created by @Lehoczky on GitHub (Oct 14, 2023).
Original GitHub issue: https://github.com/DavidAnson/markdownlint/issues/1004

Hi David 👋

What is your opinion on generating a TS type for the configuration?

Right now people using a json config file get autocompletion thanks to the markdownlint-config-schema.json, but it's not possible to get the same experience for js files.

Prettier and tailwind for example has such a type exported, which can be used in config files.

/** @type {import("@types/prettier").Options */
module.exports = {
  // ... your prettier config here
};

Another thing that could be done, is to have a defineConfig() function like vite, nuxt or astro has.

import { defineConfig } from 'astro/config'

export default defineConfig({
  // your configuration options here...
})

I've created a package as a POC (the generated type can be found here) so you can check out the idea, and whether you think it would be worth it to add this to the library.

Originally created by @Lehoczky on GitHub (Oct 14, 2023). Original GitHub issue: https://github.com/DavidAnson/markdownlint/issues/1004 Hi David 👋 What is your opinion on generating a TS type for the configuration? Right now people using a `json` config file get autocompletion thanks to the `markdownlint-config-schema.json`, but it's not possible to get the same experience for `js` files. [Prettier](https://prettier.io/docs/en/configuration#basic-configuration) and [tailwind](https://tailwindcss.com/docs/configuration) for example has such a type exported, which can be used in config files. ```js /** @type {import("@types/prettier").Options */ module.exports = { // ... your prettier config here }; ``` Another thing that could be done, is to have a `defineConfig()` function like [vite](https://vitejs.dev/config/#config-intellisense), [nuxt](https://nuxt.com/docs/guide/directory-structure/nuxt.config) or [astro](https://docs.astro.build/en/guides/configuring-astro/#the-astro-config-file) has. ```js import { defineConfig } from 'astro/config' export default defineConfig({ // your configuration options here... }) ``` I've created a [package as a POC](https://github.com/Lehoczky/markdownlint-define-config) ([the generated type can be found here](https://github.com/Lehoczky/markdownlint-define-config/blob/master/src/generated/config.ts)) so you can check out the idea, and whether you think it would be worth it to add this to the library.
kerem 2026-03-03 01:28:17 +03:00
Author
Owner

@DavidAnson commented on GitHub (Oct 14, 2023):

The idea makes sense and I see how this could be useful! Thanks for the suggestion!

If I were to add to this library, I would want to generate the types from the JSON schema because that already captures everything that's needed and it isn't necessary to duplicate information. After a very brief bit of research, these two packages seem to offer that capability:

But I also found the following package which seems to offer the same capability dynamically at runtime, thereby avoiding the need to generate/commit an artifact at all:

If it works, my preference would be for something like the last one because it seems universally applicable and limits complexity to just those scenarios that need it (i.e., pay for play).

<!-- gh-comment-id:1763069510 --> @DavidAnson commented on GitHub (Oct 14, 2023): The idea makes sense and I see how this could be useful! Thanks for the suggestion! If I were to add to this library, I would want to generate the types from the JSON schema because that already captures everything that's needed and it isn't necessary to duplicate information. After a very brief bit of research, these two packages seem to offer that capability: - https://www.npmjs.com/package/json-schema-to-typescript - https://jsontypedef.com/docs/typescript-codegen/ But I also found the following package which seems to offer the same capability dynamically at runtime, thereby avoiding the need to generate/commit an artifact at all: - https://www.npmjs.com/package/json-schema-to-ts If it works, my preference would be for something like the last one because it seems universally applicable and limits complexity to just those scenarios that need it (i.e., pay for play).
Author
Owner

@Lehoczky commented on GitHub (Oct 14, 2023):

I tried out json-schema-to-typescript but in the end I used quicktype, because it created a more readable output.

I also looked at json-schema-to-ts, but there are multiple issues open mentioning performance issues, which don't surprise me, because it can be a lot of work for the TypeScript language server to handle the conversion of big json schemas at runtime:

Fortunately, because I implemented the TypeScript type generation using the existing json schema which is the same approach you prefer, I can make draft pull request pretty quickly. I just have to migrate the code I've already written:D

<!-- gh-comment-id:1763126124 --> @Lehoczky commented on GitHub (Oct 14, 2023): I tried out [json-schema-to-typescript](https://www.npmjs.com/package/json-schema-to-typescript) but in the end I used [quicktype](https://github.com/glideapps/quicktype), because it created a more readable output. I also looked at [json-schema-to-ts](https://www.npmjs.com/package/json-schema-to-ts), but there are multiple issues open mentioning performance issues, which don't surprise me, because it can be a lot of work for the TypeScript language server to handle the conversion of big json schemas at runtime: - https://github.com/ThomasAribart/json-schema-to-ts/issues/154 - https://github.com/ThomasAribart/json-schema-to-ts/issues/168 Fortunately, because I implemented the TypeScript type generation using the existing json schema which is the same approach you prefer, I can make draft pull request pretty quickly. I just have to migrate the code I've already written:D
Author
Owner

@DavidAnson commented on GitHub (Oct 14, 2023):

The performance issues you reference above do not seem like they would be problematic in this scenario with a single/small schema and file. That said, there is an opportunity to improve the fidelity of the existing type Configuration definition. I'm not sure how everything needs to be wired up but my expectation is something like a single new .d.ts file created from the existing JSON schema using a tool like those referenced above. Then make a reference to that in the existing JSDoc comments in markdownlint.js which leads to everything composing together into markdownlint.d.ts file by the TypeScript step that's already run.

<!-- gh-comment-id:1763177836 --> @DavidAnson commented on GitHub (Oct 14, 2023): The performance issues you reference above do not seem like they would be problematic in this scenario with a single/small schema and file. That said, there is an opportunity to improve the fidelity of the existing `type Configuration` definition. I'm not sure how everything needs to be wired up but my expectation is something like a single new `.d.ts` file created from the existing JSON schema using a tool like those referenced above. Then make a reference to that in the existing JSDoc comments in `markdownlint.js` which leads to everything composing together into `markdownlint.d.ts` file by the TypeScript step that's already run.
Author
Owner

@DavidAnson commented on GitHub (Nov 14, 2023):

v0.32.0

<!-- gh-comment-id:1809572971 --> @DavidAnson commented on GitHub (Nov 14, 2023): v0.32.0
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/markdownlint#591
No description provided.