Allow type of "data" property to be set using generic type #135

Open
opened 2022-01-22 23:45:01 +00:00 by FunctionDJ · 3 comments
FunctionDJ commented 2022-01-22 23:45:01 +00:00 (Migrated from github.com)

Right now there is no way to set the type of file.data except with as. In general, as in TypeScript conveys incomplete typings for external libraries or insufficient time to fix an issue with types. You want to reduce as in a code base as much as possible in order for it to be a red flag when it comes up. However, with I/O we tap outside of types and telling our code which shape a resulting object will have is necessary. Other libraries achieve this by simply exposing a generic type param on classes or methods like this:

interface MyFrontMatter {
  title: string
  date: string
}

const { data } = matter<string, {}, MyFrontMatter>(fileContents);
const { title, date } = data; // statically typed, TS knows that title is a string, not 'any'

The advantage is that this conveys intent, that the typings are as clean as they can be. It would be great if you could add this as a third param to the types!

declare function matter<
  I extends matter.Input,
  O extends matter.GrayMatterOption<I, O>,
  MatterShape extends Record<string, unknown> // not sure about this
>(input: I | { content: I }, options?: O): matter.GrayMatterFile<I, MatterShape>

// ...

  interface GrayMatterFile<I extends Input, MatterShape extends Record<string, unknown>> {
    data: MatterShape
    content: string
    excerpt?: string
    orig: Buffer | I
    language: string
    matter: string
    stringify(lang: string): string
  }```
Right now there is no way to set the type of `file.data` except with `as`. In general, `as` in TypeScript conveys incomplete typings for external libraries or insufficient time to fix an issue with types. You want to reduce `as` in a code base as much as possible in order for it to be a red flag when it comes up. However, with I/O we tap outside of types and telling our code which shape a resulting object will have is necessary. Other libraries achieve this by simply exposing a generic type param on classes or methods like this: ```ts interface MyFrontMatter { title: string date: string } const { data } = matter<string, {}, MyFrontMatter>(fileContents); const { title, date } = data; // statically typed, TS knows that title is a string, not 'any' ``` The advantage is that this conveys intent, that the typings are as clean as they can be. It would be great if you could add this as a third param to the types! ```ts declare function matter< I extends matter.Input, O extends matter.GrayMatterOption<I, O>, MatterShape extends Record<string, unknown> // not sure about this >(input: I | { content: I }, options?: O): matter.GrayMatterFile<I, MatterShape> // ... interface GrayMatterFile<I extends Input, MatterShape extends Record<string, unknown>> { data: MatterShape content: string excerpt?: string orig: Buffer | I language: string matter: string stringify(lang: string): string }```
rocktimsaikia commented 2022-03-04 15:30:09 +00:00 (Migrated from github.com)

++ Yes. This would be quite helpful.

++ Yes. This would be quite helpful.
gd-cho commented 2022-04-05 16:04:58 +00:00 (Migrated from github.com)

yse, I have this, It kind of bothers me

yse, I have this, It kind of bothers me
HiDeoo commented 2023-01-05 18:02:37 +00:00 (Migrated from github.com)

As I've encountered this limitation multiple times, I created a small wrapper for gray-matter using zod to actually validate front matter and get proper type inference, e.g.:

import { parse } from 'zod-matter'
import { z } from 'zod'

const { data } = parse('---\nauthor: HiDeoo\n---\n# Hello world!', z.object({ author: z.string() }))
//       ^? { author: string }
As I've encountered this limitation multiple times, I created [a small wrapper](https://github.com/HiDeoo/zod-matter) for `gray-matter` using `zod` to actually validate front matter and get proper type inference, e.g.: ```ts import { parse } from 'zod-matter' import { z } from 'zod' const { data } = parse('---\nauthor: HiDeoo\n---\n# Hello world!', z.object({ author: z.string() })) // ^? { author: string } ```
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
rtlabs-llm-agents/gms-gray-matter#135
No description provided.