refactor(types): CORE-07 reconcile public declarations and preserve legacy consumers

This commit is contained in:
Harvey Zhao committed 2026-09-11 01:42:32 +08:00
1 parent ee859e4804
commit f9707bad71
34 files changed
+2806 -85

No files matched your search

+52
View File
@@ -0,0 +1,52 @@
import type { Emitter, Option, OptionInput, SubtitleUpdateEvents } from 'artplayer'
import Artplayer from 'artplayer'
const historical: Option = { container: '#player', url: '' }
const requiredUrl: string = historical.url
const art = new Artplayer(historical)
const instanceUrl: string = art.option.url
const defaultUrl: string = Artplayer.option.url
const input: OptionInput = {
container: '#player',
controls: [{ html: 42, position: 'left' }],
layers: [{ html: 43 }],
contextmenu: [{ html: 44 }],
}
void new Artplayer(input, function (instance) {
const receiverId: number = this.id
const argument: Artplayer = instance
void [receiverId, argument]
})
void new Artplayer({ container: '#player' })
art.controls.update({ name: 'numeric', html: 45, position: 'left' })
art.layers.add(() => ({ html: 46 }))
// @ts-expect-error URL must still be a string when provided.
void new Artplayer({ container: '#player', url: 42 })
// @ts-expect-error Numeric HTML does not relax other component fields.
void new Artplayer({ container: '#player', controls: [{ html: 42, position: 42 }] })
// @ts-expect-error An arbitrary object is not renderable HTML.
void new Artplayer({ container: '#player', layers: [{ html: {} }] })
const unescaped: string = Artplayer.utils.unescape('&')
const error: Error = new Artplayer.utils.ArtPlayerError('message')
const timer: Promise<void> = Artplayer.utils.sleep()
const target = { value: 1 }
const identity: typeof target = Artplayer.utils.def(target, Symbol('key'), { value: 2 })
// Existing string-key return assignments remain valid during reconciliation.
const oldDef: void = Artplayer.utils.def(target, 'key', { value: 2 })
void [requiredUrl, instanceUrl, defaultUrl, unescaped, error, timer, identity, oldDef]
const emitter: Emitter<{ ready: [number] }> = new Artplayer.Emitter<{ ready: [number] }>('historically-ignored')
emitter.on('ready', function (value) {
const id: number = this.id
const payload: number = value
void [id, payload]
}, { id: 1 }).once('ready', () => {}).emit('ready', 1).off('ready')
// @ts-expect-error Typed event maps reject wrong payloads.
emitter.emit('ready', 'bad')
// @ts-expect-error Typed event maps reject unknown names.
emitter.on('missing', () => {})
const open = new Artplayer.Emitter()
open.on(Symbol.for('event'), (...values) => values.length).emit(Symbol.for('event'), 1, 'two')
const before = (cues: SubtitleUpdateEvents['subtitleBeforeUpdate'][0]) => cues.map(cue => cue.text)
art.on('subtitleBeforeUpdate', before).once('subtitleAfterUpdate', before)
art.emit('subtitleBeforeUpdate', []).off('subtitleBeforeUpdate', before)
+20
View File
@@ -0,0 +1,20 @@
import type { Option } from 'artplayer'
import Artplayer from 'artplayer'
// These legal historical declarations expose known runtime mismatches.
// Keep them compiling until a compatible, reviewed resolution exists.
const option: Option = { container: '#player', url: '' }
const requiredUrl: string = option.url
const art = new Artplayer(option)
const registration: Promise<Artplayer['plugins']> = art.plugins.add(() => ({ name: 'legacy' }))
const toggle: void = art.toggle()
const debounced: number = Artplayer.utils.debounce(() => 1, 10, {})()
const throttled: number = Artplayer.utils.throttle(() => 1, 10)()
const descriptor: void = Artplayer.utils.def({}, 'value', { value: 1 })
const updated: Artplayer['setting'] = art.setting.update({ name: 'entry', html: 'Entry' })
const removed: Artplayer['setting'] = art.setting.remove('entry')
art.on('subtitleBeforeUpdate', (cue) => {
const historicalCue: VTTCue = cue
void historicalCue
})
void [requiredUrl, registration, toggle, debounced, throttled, descriptor, updated, removed]
+3 -2
View File
@@ -1,4 +1,4 @@
import type { Events } from 'artplayer'
import type { Events, Emitter as PublicEmitter } from 'artplayer'
import Emitter from '../../packages/artplayer/src/utils/emitter'
const symbol = Symbol('message')
@@ -12,6 +12,7 @@ class TypedEmitter extends Emitter<Messages> {
count = 0
}
const events = new TypedEmitter()
const publicShape: PublicEmitter<Messages> = events
const context = { total: 0 }
const chain: TypedEmitter = events.on('value', function (count, label) {
this.total += count
@@ -39,4 +40,4 @@ events.on('ready', contextListener, { total: 'zero' })
function contextListener(this: { total: number }) {
return this.total
}
void chain
void [chain, publicShape]
+6 -7
View File
@@ -1,4 +1,4 @@
import type { Option, ResolvedOption } from '../../packages/artplayer/src/option/types'
import type { Option, OptionInput, ResolvedOption } from '../../packages/artplayer/src/option/types'
import createDefaults from '../../packages/artplayer/src/option/defaults'
import resolveOption from '../../packages/artplayer/src/option/resolve'
@@ -25,9 +25,8 @@ resolved.subtitle.onVttLoad = () => 42
// @ts-expect-error Application fields retain their own type.
extended.application.token = 'invalid'
// Historical public declaration gaps; CORE-07 must replace these with positive checks.
// @ts-expect-error Runtime accepts an omitted URL, but the current public Option requires it.
const omittedUrl: Option = { container: '#player' }
// @ts-expect-error Runtime accepts numeric control HTML, but the current public type excludes it.
const numericHtml: NonNullable<Option['controls']>[number] = { html: 42, position: 'left' }
void [omittedUrl, numericHtml]
const omittedUrl: OptionInput = { container: '#player' }
const numericHtml: NonNullable<OptionInput['controls']>[number] = { html: 42, position: 'left' }
const expanded = resolveOption({ ...omittedUrl, controls: [numericHtml] }, createDefaults())
const defaultUrl: string = expanded.url
void [omittedUrl, numericHtml, defaultUrl]