Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Export library types for external use. #4106

Closed
vknowles-rv opened this issue Jan 26, 2023 · 3 comments
Closed

Export library types for external use. #4106

vknowles-rv opened this issue Jan 26, 2023 · 3 comments
Labels
👕 TypeScript TypeScript typings issue

Comments

@vknowles-rv
Copy link

vknowles-rv commented Jan 26, 2023

Is your feature request related to a problem? Please describe.

It would be great to have the ability to reference the types vee-validate has defined. My use case is specific to the i18n, as configuration related items for our framework is abstracted to a config/ folder to not clutter the framework bootstrapping process.

Describe the solution you'd like

At a minimum export RootI18nDictionary, PartialI18nDictionary and FieldValidationMetaInfo, but might be worth combing over entire lib to see what types are feasible for export.

Describe alternatives you've considered

In the interim, I've copied the types from node_modules up. This isn't a viable long term solution, though.

One could infer type, but localize has overloads and this requires medium-advance typescript knowledge. Ex:

import type { localize } from "@vee-validate/i18n";

type LocalizedParameter = typeof localize extends (infer A) ? A : unknown;
@vknowles-rv
Copy link
Author

Still unable to extract dictionary from i18n due to overload, but here is an example of pulling out form and field options

import { useForm, useField } from "vee-validate";

type LibFormOptions<S extends Record<string, unknown>> = NonNullable<typeof useForm<S> extends (...args: infer A) => unknown ? A[0] : Record<string, unknown>>;
type LibFieldOptions<S> = NonNullable<typeof useField<S> extends (...args: infer A) => unknown ? A[2] : Partial<Record<string, unknown>>>;

@vknowles-rv
Copy link
Author

vknowles-rv commented Jan 26, 2023

Incase this is helpful, these are helpers to integrate with a Pinia store.

This addresses (albeit externally) the notice tip

Notice the errors are displayed immediately, this is because when using useFieldModel vee-validate can no longer detect the field touched state. If you want to control the validation behavior in this case, then you need to implement a custom component with useField or <Field>.
const useStoreForm = <
    State extends Record<string, unknown>, 
    FormOptions extends {} = LibFormOptions<State>, 
    FieldOptions extends {} = LibFieldOptions<State[keyof State]> & {fields: {[P in keyof State]: LibFieldOptions<State[P]>}},
    FormContext = ReturnType<typeof useForm<State>>, 
    ValidationState = ReturnType<typeof useStoreState<State>>
>(options: FormOptions, state: State, fieldOptions?: FieldOptions): {formContext: FormContext, validationState: ValidationState} => {
    const formContext = useForm(options) as unknown as FormOptions;

    const validationState = useStoreState(state, fieldOptions);

    return {formContext: formContext as unknown as FormContext, validationState: validationState as ValidationState};
}

const useStoreState = <
    State extends Record<string, unknown>, 
    FieldOptions extends {} = LibFieldOptions<State[keyof State]> & {fields: {[P in keyof State]: LibFieldOptions<State[P]>}},
    Result extends Record<string, Ref<unknown>> = {[P in keyof State]: Ref<State[P]>}, 
    FieldContexts extends Record<string, ReturnType<typeof useField<unknown>>> = {[P in keyof State]: ReturnType<typeof useField<State[P]>>}
>(state: State, fieldOptions?: FieldOptions): {state: Result, fieldContexts: FieldContexts} => {
    const newState: Record<string, unknown> = {};
    const fieldContexts: Record<string, ReturnType<typeof useField>> = {};

    for (const [field, value] of Object.entries(state)) {
        const context = useField(
            field, 
            undefined, // Relies on schema rules
            {
                initialValue: value, 
                ...get((fieldOptions as any)?.fields, field, {}),
            }
        );

        newState[field] = context.value;
        fieldContexts[field] = context;
    }
    return {state: newState as Result, fieldContexts: fieldContexts as FieldContexts};
}

const useStoreStateToRaw = <
    State extends Record<string, unknown>, 
    Result = {[P in keyof State]: State[P] extends Ref<infer V> ? V : State[P]}
>(state: State): Result => {
    const raw: Record<string, unknown> = {};

    for (const [field, value] of Object.entries(state)) {
        raw[field] = unref(value);
    }

    return raw as Result;
}

useStoreStateToRaw allows for an easier resetForm({values: whatev}) pass since useField returns computed references.

@logaretm logaretm added the 👕 TypeScript TypeScript typings issue label Jan 31, 2023
@logaretm
Copy link
Owner

I think it makes sense to expose the ones you listed. Combing over the entire lib is not going to help much as I pretty much exposed what I thought was enough without exposing fragile internal types.

Will try to do a quick release with those exposed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
👕 TypeScript TypeScript typings issue
Projects
None yet
Development

No branches or pull requests

2 participants