From bb3d274db64fe662ad01780ca5eadbc263f6f759 Mon Sep 17 00:00:00 2001 From: Kagami Sascha Rosylight Date: Sun, 18 Dec 2022 13:13:05 +0900 Subject: [PATCH] refactor(client): add proper types to `never[]` (#9340) --- packages/client/src/components/mfm.ts | 9 ++-- packages/client/src/scripts/array.ts | 2 +- .../client/src/scripts/collect-page-vars.ts | 38 +++++++++++++---- packages/client/src/scripts/physics.ts | 16 ++++---- packages/client/src/store.ts | 41 ++++++++++++++++--- 5 files changed, 78 insertions(+), 28 deletions(-) diff --git a/packages/client/src/components/mfm.ts b/packages/client/src/components/mfm.ts index 688857a49..5b5b1caae 100644 --- a/packages/client/src/components/mfm.ts +++ b/packages/client/src/components/mfm.ts @@ -54,13 +54,13 @@ export default defineComponent({ return t.match(/^[0-9.]+s$/) ? t : null; }; - const genEl = (ast: mfm.MfmNode[]) => concat(ast.map((token): VNode[] => { + const genEl = (ast: mfm.MfmNode[]) => ast.map((token): VNode | string | (VNode | string)[] => { switch (token.type) { case 'text': { const text = token.props.text.replace(/(\r\n|\n|\r)/g, '\n'); if (!this.plain) { - const res = []; + const res: (VNode | string)[] = []; for (const t of text.split('\n')) { res.push(h('br')); res.push(t); @@ -317,12 +317,13 @@ export default defineComponent({ } default: { - console.error('unrecognized ast type:', token.type); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + console.error('unrecognized ast type:', (token as any).type); return []; } } - })); + }).flat(Infinity) as (VNode | string)[]; // Parse ast to DOM return h('span', genEl(ast)); diff --git a/packages/client/src/scripts/array.ts b/packages/client/src/scripts/array.ts index 26c6195d6..4620c8b73 100644 --- a/packages/client/src/scripts/array.ts +++ b/packages/client/src/scripts/array.ts @@ -123,7 +123,7 @@ export function lessThan(xs: number[], ys: number[]): boolean { * Returns the longest prefix of elements that satisfy the predicate */ export function takeWhile(f: Predicate, xs: T[]): T[] { - const ys = []; + const ys: T[] = []; for (const x of xs) { if (f(x)) { ys.push(x); diff --git a/packages/client/src/scripts/collect-page-vars.ts b/packages/client/src/scripts/collect-page-vars.ts index a4096fb2c..76b68beaf 100644 --- a/packages/client/src/scripts/collect-page-vars.ts +++ b/packages/client/src/scripts/collect-page-vars.ts @@ -1,42 +1,62 @@ -export function collectPageVars(content) { - const pageVars = []; - const collect = (xs: any[]) => { +interface StringPageVar { + name: string, + type: 'string', + value: string +} + +interface NumberPageVar { + name: string, + type: 'number', + value: number +} + +interface BooleanPageVar { + name: string, + type: 'boolean', + value: boolean +} + +type PageVar = StringPageVar | NumberPageVar | BooleanPageVar; + +export function collectPageVars(content): PageVar[] { + const pageVars: PageVar[] = []; + const collect = (xs: any[]): void => { for (const x of xs) { if (x.type === 'textInput') { pageVars.push({ name: x.name, type: 'string', - value: x.default || '' + value: x.default || '', }); } else if (x.type === 'textareaInput') { pageVars.push({ name: x.name, type: 'string', - value: x.default || '' + value: x.default || '', }); } else if (x.type === 'numberInput') { pageVars.push({ name: x.name, type: 'number', - value: x.default || 0 + value: x.default || 0, }); } else if (x.type === 'switch') { pageVars.push({ name: x.name, type: 'boolean', - value: x.default || false + value: x.default || false, }); } else if (x.type === 'counter') { pageVars.push({ name: x.name, type: 'number', - value: 0 + value: 0, }); } else if (x.type === 'radioButton') { pageVars.push({ name: x.name, type: 'string', - value: x.default || '' + value: x.default || '', }); } else if (x.children) { collect(x.children); diff --git a/packages/client/src/scripts/physics.ts b/packages/client/src/scripts/physics.ts index 9e657906c..f0a5b0fdd 100644 --- a/packages/client/src/scripts/physics.ts +++ b/packages/client/src/scripts/physics.ts @@ -55,13 +55,13 @@ export function physics(container: HTMLElement) { //wallLeft, ]); - const objEls = Array.from(container.children); - const objs = []; + const objEls = Array.from(container.children) as HTMLElement[]; + const objs: Matter.Body[] = []; for (const objEl of objEls) { const left = objEl.dataset.physicsX ? parseInt(objEl.dataset.physicsX) : objEl.offsetLeft; const top = objEl.dataset.physicsY ? parseInt(objEl.dataset.physicsY) : objEl.offsetTop; - let obj; + let obj: Matter.Body; if (objEl.classList.contains('_physics_circle_')) { obj = Matter.Bodies.circle( left + (objEl.offsetWidth / 2), @@ -84,7 +84,7 @@ export function physics(container: HTMLElement) { } ); } - objEl.id = obj.id; + objEl.id = obj.id.toString(); objs.push(obj); } @@ -109,10 +109,10 @@ export function physics(container: HTMLElement) { render.mouse = mouse; for (const objEl of objEls) { - objEl.style.position = `absolute`; - objEl.style.top = 0; - objEl.style.left = 0; - objEl.style.margin = 0; + objEl.style.position = 'absolute'; + objEl.style.top = '0'; + objEl.style.left = '0'; + objEl.style.margin = '0'; } window.requestAnimationFrame(update); diff --git a/packages/client/src/store.ts b/packages/client/src/store.ts index 3971214af..061e1913d 100644 --- a/packages/client/src/store.ts +++ b/packages/client/src/store.ts @@ -2,11 +2,34 @@ import { markRaw, ref } from 'vue'; import { Storage } from './pizzax'; import { Theme } from './scripts/theme'; -export const postFormActions = []; -export const userActions = []; -export const noteActions = []; -export const noteViewInterruptors = []; -export const notePostInterruptors = []; +interface PostFormAction { + title: string, + handler: (form: T, update: (key: unknown, value: unknown) => void) => void; +} + +interface UserAction { + title: string, + handler: (user: UserDetailed) => void; +} + +interface NoteAction { + title: string, + handler: (note: Note) => void; +} + +interface NoteViewInterruptor { + handler: (note: Note) => unknown; +} + +interface NotePostInterruptor { + handler: (note: FIXME) => unknown; +} + +export const postFormActions: PostFormAction[] = []; +export const userActions: UserAction[] = []; +export const noteActions: NoteAction[] = []; +export const noteViewInterruptors: NoteViewInterruptor[] = []; +export const notePostInterruptors: NotePostInterruptor[] = []; // TODO: それぞれいちいちwhereとかdefaultというキーを付けなきゃいけないの冗長なのでなんとかする(ただ型定義が面倒になりそう) // あと、現行の定義の仕方なら「whereが何であるかに関わらずキー名の重複不可」という制約を付けられるメリットもあるからそのメリットを引き継ぐ方法も考えないといけない @@ -266,11 +289,17 @@ type Plugin = { ast: any[]; }; +interface Watcher { + key: string; + callback: (value: unknown) => void; +} + /** * 常にメモリにロードしておく必要がないような設定情報を保管するストレージ(非リアクティブ) */ import lightTheme from '@/themes/l-light.json5'; import darkTheme from '@/themes/d-green-lime.json5'; +import { Note, UserDetailed } from 'misskey-js/built/entities'; export class ColdDeviceStorage { public static default = { @@ -289,7 +318,7 @@ export class ColdDeviceStorage { sound_channel: { type: 'syuilo/square-pico', volume: 1 }, }; - public static watchers = []; + public static watchers: Watcher[] = []; public static get(key: T): typeof ColdDeviceStorage.default[T] { // TODO: indexedDBにする