work-in-progress atproto PDS
typescript atproto pds atcute
4
fork

Configure Feed

Select the types of activity you want to include in your feed.

refactor: match as() closer to reference implementation

Mary 8052748d 24b706ce

+52 -24
+52 -24
packages/danaus/src/web/forms/index.ts
··· 55 55 } & ((message: string) => FormIssue); 56 56 57 57 export type FieldsProxy<T> = { 58 - [K in keyof T]: T[K] extends Record<string, unknown> ? FieldsProxy<T[K]> & FieldAccessor : FieldAccessor; 59 - } & FieldAccessor; 58 + [K in keyof T]: T[K] extends Record<string, unknown> 59 + ? FieldsProxy<T[K]> & FieldAccessor<T[K]> 60 + : FieldAccessor<T[K]>; 61 + } & FieldAccessor<T>; 62 + 63 + export type FormFieldValue = string | string[] | number | boolean | File | File[]; 60 64 61 - export interface FieldAccessor { 65 + export type FormFieldType<T> = { 66 + [K in keyof InputTypeMap]: T extends InputTypeMap[K] ? K : never; 67 + }[keyof InputTypeMap]; 68 + 69 + export interface FieldAccessor<Value> { 62 70 /** returns the current input value for this field */ 63 - value(): unknown; 71 + value(): Value; 64 72 /** returns validation issues for this exact field path */ 65 73 issues(): { path: (string | number)[]; message: string }[]; 66 74 /** returns validation issues for this field and all nested fields */ 67 75 allIssues(): { path: (string | number)[]; message: string }[]; 68 76 /** returns props for an input element */ 69 - as(type: InputType, inputValue?: string): Record<string, unknown>; 77 + as<T extends FormFieldType<Value>>(...args: AsArgs<T, Value>): Record<string, unknown>; 70 78 } 71 79 72 - type InputType = 73 - | 'text' 74 - | 'email' 75 - | 'password' 76 - | 'number' 77 - | 'range' 78 - | 'search' 79 - | 'tel' 80 - | 'url' 81 - | 'hidden' 82 - | 'submit' 83 - | 'checkbox' 84 - | 'radio' 85 - | 'select' 86 - | 'select multiple' 87 - | 'file' 88 - | 'file multiple'; 80 + type InputTypeMap = { 81 + text: string; 82 + email: string; 83 + password: string; 84 + url: string; 85 + tel: string; 86 + search: string; 87 + number: number; 88 + range: number; 89 + date: string; 90 + 'datetime-local': string; 91 + time: string; 92 + month: string; 93 + week: string; 94 + color: string; 95 + checkbox: boolean | string[]; 96 + radio: string; 97 + file: File; 98 + hidden: string; 99 + submit: string; 100 + button: string; 101 + reset: string; 102 + image: string; 103 + select: string; 104 + 'select multiple': string[]; 105 + 'file multiple': File[]; 106 + }; 107 + 108 + type InputType = keyof InputTypeMap; 109 + 110 + type AsArgs<Type extends InputType, Value> = Type extends 'checkbox' 111 + ? Value extends string[] 112 + ? [type: Type, value: Value[number] | (string & {})] 113 + : [type: Type] 114 + : Type extends 'radio' | 'submit' | 'hidden' 115 + ? [type: Type, value: Value | (string & {})] 116 + : [type: Type]; 89 117 // #endregion 90 118 91 119 // #region async local storage ··· 352 380 353 381 const pathKey = buildName() || '$'; 354 382 355 - const accessor: FieldAccessor = { 383 + const accessor = { 356 384 value: getValue, 357 385 issues: () => { 358 386 const issues = getIssues()[pathKey] ?? []; ··· 365 393 const issues = getIssues()[pathKey] ?? []; 366 394 return issues.map((issue) => ({ path: issue.path, message: issue.message })); 367 395 }, 368 - as: (type, inputValue) => { 396 + as: (type: InputType, inputValue?: string) => { 369 397 const baseName = buildName(); 370 398 const issues = getIssues()[pathKey] ?? []; 371 399 const pathStr = path.join('.');