Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat!: change customPrettifiers to a Map #552

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

Frederick888
Copy link

@Frederick888 Frederick888 commented Jan 14, 2025

In [1], LevelPrettifierExtras and PrettifierExtras were merged to solve
a typing issue [2]. This was suboptimal as the additional extra
attributes that only the 'level' prettifier had were exposed to other
prettifiers too.

To allow the additional attributes while keeping 'level' prettifier's
type separate, this patch uses an intersection Map type
CustomPrettifiers instead.

This is a breaking change.

[1] #551
[2] #550


This PR stacks on #551 to avoid conflicts down the line, so only the 2nd commit is actually relevant. (I'm not sure how to do cross-fork stacked PRs in GitHub...)

I guess the first commit in this PR will automatically disappear once #551 is (fast-forward?) merged. To review before that, we can use the link to the 2nd commit: 38cdaf27e1e2a1f33203aa249637e6e6d3086b78

The fourth parameter of the 'level' custom prettifier -- extras -- used
to have a separate type as pino-pretty offered two additional attributes
to this particular prettifier.

However since it used a Record<string, T> type, TypeScript required all
values to be compatible with each other. So when users tried to use the
extras parameter for 'level', it caused

    error TS2322: Type '{ level: (_level: string | object, _levelKey: string, _log: object, { labelColorized }: PrettifierExtras<LevelPrettifierExtras>) => string; }' is not assignable to type 'Record<string, Prettifier<object>> & { level?: Prettifier<LevelPrettifierExtras> | undefined; }'.
    Type '{ level: (_level: string | object, _levelKey: string, _log: object, { labelColorized }: PrettifierExtras<LevelPrettifierExtras>) => string; }' is not assignable to type 'Record<string, Prettifier<object>>'.
        Property 'level' is incompatible with index signature.
        Type '(_level: string | object, _levelKey: string, _log: object, { labelColorized }: PrettifierExtras<LevelPrettifierExtras>) => string' is not assignable to type 'Prettifier<object>'.
            Types of parameters '__3' and 'extras' are incompatible.
            Type 'PrettifierExtras<object>' is not assignable to type 'PrettifierExtras<LevelPrettifierExtras>'.
                Type '{ colors: Colorette; }' is missing the following properties from type 'LevelPrettifierExtras': label, labelColorized

    115     customPrettifiers: {
            ~~~~~~~~~~~~~~~~~

This patch remedies this issue by merging LevelPrettifierExtras into
PrettifierExtras. These types are not exported directly, therefore users,
including those who leverage TypeScript utility types to extract these
types, should be able to upgrade directly.

Fixes pinojs#550
@Frederick888 Frederick888 changed the title Custom prettifiers map feat!: change customPrettifiers to a Map Jan 14, 2025
In [1], LevelPrettifierExtras and PrettifierExtras were merged to solve
a typing issue [2]. This was suboptimal as the additional extra
attributes that only the 'level' prettifier had were exposed to other
prettifiers too.

To allow the additional attributes while keeping 'level' prettifier's
type separate, this patch uses an intersection Map type
CustomPrettifiers instead.

This is a breaking change.

[1] pinojs#551
[2] pinojs#550
@jsumners
Copy link
Member

I'm not clear. What is this solving? It seems to just be making the code more complicated.

@Frederick888
Copy link
Author

Frederick888 commented Jan 14, 2025

@jsumners Indeed it can be a little confusing as on the JavaScript side, not only does it solve nothing, it also introduces a breaking change. The issue actually came only from the TypeScript side. Allow me to share some context.

In #551 to solve #550, LevelPrettifierExtras and PrettifierExtras were merged. However the downside of #551 was that 'level' prettifier's additional extra attributes started leaking into other prettifiers. Practically, this means users can see them when doing auto-completion and use them where they are not available:

image

This was obviously not the intention of the original Record<string, Prettifier> & { level?: Prettifier<LevelPrettifierExtras> }. After doing some research, I reached the conclusion that having a separate 'level' prettifier type was simply impossible with Record or interface { ... }, and a Map had to be used instead.

So now on this PR:
image
image

If we don't want to break existing JavaScript users, I can instead allow customPrettifiers to accept both plain objects and Maps, and convert all Maps to objects in prettyFactory (options).

In index.d.ts, I can also either leave it as it is (so that it'll be a breaking change to TypeScript users only), or allow both Records and Maps (so that it won't be a breaking change, but users will have to use Maps whenever they want to use the additional extra attributes for the 'level' prettifier, which is kinda confusing imho).

Please let me know what you think :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants