#Typing for Record, that can be a type or Record

15 messages · Page 1 of 1 (latest)

snow radish
#
type FieldError = string;
type FieldErrors = {
    __errors?: FieldError[];
};

type FieldValidation = FieldErrors & {
    addError: (message: string) => void;
};

type FormValidation = Record<string, FieldValidation | Record<string, FieldValidation>>;

function isObject(value: Record<string, unknown> | undefined): value is Record<string, unknown> {
  return typeof value === 'object' && value !== null && !Array.isArray(value);
}

async function recursive(root: Record<string, unknown>, current: Record<string, unknown>): Promise<FormValidation> {
    const formValidation: FormValidation = {};

    for (const [key, value] of Object.entries(current)) {
        if (isObject(current)) {
            formValidation[key] = await recursive(root, current);
        }
    }

    return formValidation;
}

In the example above , I have FormValidation is currently defined as

type FormValidation = Record<string, FieldValidation | Record<string, FieldValidation>>;

I think I need to somehow narrow the type or let tsc know whether I am dealing with a FiedValdiation or Record<string, FieldValidation on this line

formValidation[key] = await validate(formData, path, value);

The error I get here is

type 'FormValidation' is not assignable to type 'FieldValidation | Record<string, FieldValidation>'.
Type 'FormValidation' is not assignable to type 'FieldValidation'.
Property 'addError' is missing in type 'FormValidation' but required in type '{ addError: (message: string) => void; }'.ts(2322)
index.d.ts(108, 5): 'addError' is declared here.

vivid stump
#

btw you don't have an await validate(formData, path, value); line in your playground

snow radish
#

FormValidation is definitely wrong but I'm not sure how to type it to be FieldValidation or a similar record

snow radish
#

or is this assertion ok

formValidation[key] = await validate(formData, path, value) as Record<string, FieldValidation>;
vivid stump
#

well

#

there's only one way to find out

snow radish
#

it compiles but I wish there was a way without the assertion

vivid stump
nova sorrel
#

judging this statement let tsc know whether I am dealing with a FiedValdiation or Record<string, FieldValidation on this line

can you not say this ? ```ts
type FieldValidation = Record<string, FieldValidation> | FieldValidation;

sorry if it's not correct, still learning here 😛
vivid stump
#

but also that type would be incorrect, yes, FieldValidation cannot be | itself

snow radish
#

I settled on this

export type FormValidation = {
  [name: string]: FieldValidation | FormValidation;
};
vivid stump
#

!close