Conversation
wesrupert
commented
Apr 1, 2026
- Migrate Credits widget to React
- Clean up widget form types
1510eca to
8b1b29f
Compare
| export type TInputMetadata<T = string> = | ||
| | ITextMetadata | ||
| | INumberMetadata | ||
| | ISliderMetadata | ||
| | ITextBoolMetadata | ||
| | ICheckboxGroupMetadata | ||
| | IRadioGroupMetadata | ||
| | IListMetadata<T>; | ||
|
|
||
| interface IBaseMetadata { | ||
| export interface IBaseMetadata { |
There was a problem hiding this comment.
This union type was hiding some potential bugs, so I moved to using the underlying base interface as our main export:
- There was no way for other widgets to reference the base class for input types that don't have a hand-written type yet
- The inference from
TInputMetadata<unknown>was casting custom types to incorrect subtypes, like SponsorBanner'simagepickerinput was casting as aIListMetadatasince it was the only type with.options
| type TCreditsMeta = PartialRec< | ||
| keyof ICreditsState['data']['settings'] | 'themes' | `_${string}`, | ||
| IBaseMetadata | ||
| >; |
There was a problem hiding this comment.
After struggling a bit to figure out how widget settings are synced via this system, I wanted to make it explicit in the types. This record type forces each section to either (a) use a synced value defined above, or (b) be explicit in its unsynced behavior via an underscore. See creditsMeta for more details.
| '{new_follower_count}', | ||
| ].join(', '), | ||
| }), | ||
| _includes: { |
There was a problem hiding this comment.
This is where the TCreditsMeta magic helps make the config explicit. If this were named includes, TypeScript will now emit the following:
Diagnostics: Object literal may only specify known properties, and 'includes' does not exist in type 'Partial<Record< "theme" | "credit_title" | "credit_subtitle" | "background_color" | "font_color" | "font_size" | "font" | "muted_chatters" | "bits" | "subscribers" | "moderators" | "donations" | ... 11 more ... | `_${string}`, IBaseMetadata> >'. [2353]
Same thing for typos like font_size vs fontsize, and even widget API mismatches like Credits' font_size vs Event List's text_size.
| value: theme, | ||
| })), | ||
| }), | ||
| background_color: metadata.color({ |
There was a problem hiding this comment.
Review question: how does the new system handle previews? I didn't see anywhere in the reference code where event list was handling preview.
| height: 200, | ||
| x: 1, | ||
| y: 1, | ||
| anchor: AnchorPoint.North, |
There was a problem hiding this comment.
I guessed at this value. Was it defined in the old code somewhere?