From a8abb03d1785791ab40e57ab49c87640914532c9 Mon Sep 17 00:00:00 2001 From: かっこかり <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Sun, 6 Jul 2025 19:36:11 +0900 Subject: refactor(frontend): Formまわりの型強化 (#16260) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor(frontend): Formまわりの型強化 * fix * avoid non-null assertion and add null check for safety * refactor * avoid non-null assertion and add null check for safety * Update clip.vue --------- Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com> --- packages/frontend/src/utility/form.ts | 122 +++++++++++++++++++++++----------- 1 file changed, 82 insertions(+), 40 deletions(-) (limited to 'packages/frontend/src/utility/form.ts') diff --git a/packages/frontend/src/utility/form.ts b/packages/frontend/src/utility/form.ts index 1032e97ac9..2b765dc714 100644 --- a/packages/frontend/src/utility/form.ts +++ b/packages/frontend/src/utility/form.ts @@ -5,55 +5,59 @@ import * as Misskey from 'misskey-js'; -type EnumItem = string | { +export type EnumItem = string | { label: string; - value: string; + value: unknown; }; type Hidden = boolean | ((v: any) => boolean); -export type FormItem = { +interface FormItemBase { label?: string; + hidden?: Hidden; +} + +export interface StringFormItem extends FormItemBase { type: 'string'; default?: string | null; description?: string; required?: boolean; - hidden?: Hidden; multiline?: boolean; treatAsMfm?: boolean; -} | { - label?: string; +} + +export interface NumberFormItem extends FormItemBase { type: 'number'; default?: number | null; description?: string; required?: boolean; - hidden?: Hidden; step?: number; -} | { - label?: string; +} + +export interface BooleanFormItem extends FormItemBase { type: 'boolean'; default?: boolean | null; description?: string; - hidden?: Hidden; -} | { - label?: string; +} + +export interface EnumFormItem extends FormItemBase { type: 'enum'; default?: string | null; required?: boolean; - hidden?: Hidden; enum: EnumItem[]; -} | { - label?: string; +} + +export interface RadioFormItem extends FormItemBase { type: 'radio'; default?: unknown | null; required?: boolean; - hidden?: Hidden; options: { label: string; value: unknown; }[]; -} | { - label?: string; +} + +export interface RangeFormItem extends FormItemBase { type: 'range'; default?: number | null; description?: string; @@ -62,42 +66,80 @@ export type FormItem = { min: number; max: number; textConverter?: (value: number) => string; - hidden?: Hidden; -} | { - label?: string; +} + +export interface ObjectFormItem extends FormItemBase { type: 'object'; default?: Record | null; - hidden: Hidden; -} | { - label?: string; +} + +export interface ArrayFormItem extends FormItemBase { type: 'array'; default?: unknown[] | null; - hidden: Hidden; -} | { +} + +export interface ButtonFormItem extends FormItemBase { type: 'button'; content?: string; - hidden?: Hidden; action: (ev: MouseEvent, v: any) => void; -} | { +} + +export interface DriveFileFormItem extends FormItemBase { type: 'drive-file'; defaultFileId?: string | null; - hidden?: Hidden; validate?: (v: Misskey.entities.DriveFile) => Promise; -}; +} + +export type FormItem = + StringFormItem | + NumberFormItem | + BooleanFormItem | + EnumFormItem | + RadioFormItem | + RangeFormItem | + ObjectFormItem | + ArrayFormItem | + ButtonFormItem | + DriveFileFormItem; export type Form = Record; +export type FormItemWithDefault = FormItem & { + default: unknown; +}; + +export type FormWithDefault = Record; + +type GetRadioItemType = Item['options'][number]['value']; +type GetEnumItemType = E extends { value: unknown } ? E['value'] : E; + +type InferDefault = T extends { default: infer D } + ? D extends undefined ? Fallback : D + : Fallback; + +type NonNullableIfRequired = + Item extends { required: false } ? T | null | undefined : NonNullable; + type GetItemType = - Item['type'] extends 'string' ? string : - Item['type'] extends 'number' ? number : - Item['type'] extends 'boolean' ? boolean : - Item['type'] extends 'radio' ? unknown : - Item['type'] extends 'range' ? number : - Item['type'] extends 'enum' ? string : - Item['type'] extends 'array' ? unknown[] : - Item['type'] extends 'object' ? Record : - Item['type'] extends 'drive-file' ? Misskey.entities.DriveFile | undefined : - never; + Item extends StringFormItem + ? NonNullableIfRequired, Item> + : Item extends NumberFormItem + ? NonNullableIfRequired, Item> + : Item extends BooleanFormItem + ? boolean + : Item extends RadioFormItem + ? GetRadioItemType + : Item extends RangeFormItem + ? NonNullableIfRequired, Item> + : Item extends EnumFormItem + ? GetEnumItemType + : Item extends ArrayFormItem + ? NonNullableIfRequired, Item> + : Item extends ObjectFormItem + ? NonNullableIfRequired>, Item> + : Item extends DriveFileFormItem + ? Misskey.entities.DriveFile | undefined + : never; export type GetFormResultType = { [P in keyof F]: GetItemType; -- cgit v1.2.3-freya