#Initializing an object with definite keys

24 messages · Page 1 of 1 (latest)

light bison
#

Hi,

I'm trying to initialize an object that looks like this:

type InitialValues = Record<keyof typeof formSchema, string>;

where FormSchema is an object that defines validator functions

const formSchema = {
  username: usernameValidator;
  email: emailValidator;
  ...
}

and I want all the initial values to be blank. Is there any way I can do this? I would do it like this if I were using JavaScript:

let initialValues: InitialValues = {}
for (const name of Object.keys(formSchema)) {
    initialValues[name] = '';
}

but that gives me the error

Type '{}' is not assignable to type 'Record<keyof TypeOf<formSchema>, string>'

Any help for the right way to approach this would be great. Thank you!

coarse plover
#

It gives you the error because it expects that the value you assign to initialValues already has all of the properties required by Record<keyof FormSchema, string>.

light bison
#

Yeah, I was thinking that... Is something like a type assertion the only way to handle this? I don't know how to map from the keys of formSchema to initialValues otherwise

#

Sorry to keep editing... Trying to be clear

coarse plover
#

Well, okay, first things first.

#

The only declarations that should be capitalised in your code are of types, enums and classes.

#

As such, it'd be better for you to write:

const formSchema = {
  username: usernameValidator;
  email: emailValidator;
  ...
} as const;
#

From here, you can create a type based on this object:

type FormSchema = typeof formSchema;```
light bison
#

Sorry, that was a typo trying to copy over the code in a way that gives it more context... I think I fixed it

coarse plover
#

In order to get the keys of this object you can do keyof FormSchema.

#

Your original approach has two issues.

coarse plover
#

I'm not sure what type InitialValues is, but I assume it is the same as FormSchema.

#

The second issue is that Object.keys(obj) returns string[].

#

You need to cast this by doing: Object.keys(formSchema) as (keyof FormSchema)[].

#
const initialValues: Partial<InitialValues> = {};
for (const name of Object.keys(formSchema) as (keyof FormSchema)[]) {
  initialValues[name] = '';
}
#

You should end up with something like this.

light bison
#

Thanks. Yeah I was trying to find some way to do it without casting

coarse plover
#

There is a more functional way of doing it, and that's through using Object.fromEntries().

#
const schemaNames = (Object.keys(schema.shape) as (keyof FormSchema)[]);
const initialValues = Object.fromEntries(
  schemaNames.map<[SchemaNames, string]>((key) => [key, ''])
) as InitialValues;
#

Let me know if this works for you.

light bison
#

Yeah, I think it does. There's no way to do it without casting, right?

#

Yeah I think I'm good now. Thanks for the help

#

!resolved