1
votes

I have a problem with typescript Generic

code:

type ValidationError<S> = Record<keyof S, string>;

function validateType<S>(
  key: keyof S,
  value: string,
  type: FieldType | FieldType[],
  errors: ValidationError<S>[],
): void {
  switch (type) {
    case 'email': {
      if (!validator.isEmail(value)) {
        const error: ValidationError<S> = {
          [key]: 'error!',
        };

        errors.push(error);
      }
    }
  }
}

But I have typescript error "TS2322: Type '{ [x: string]: string; }' is not assignable to type 'Record '." on the:

const error: ValidationError<S> = {
  [key]: 'error!',
};

Can someone describe why error occurs and how to fix it?

1

1 Answers

2
votes

This is a tricky one. This is what I suspect is happening. When you create an object with dynamic keys using bracket notations, I think typescript automatically assumes that that dynamic value is of type string. So when you do:

const error = {[key]: "something"} /// type => {[x: string]: string};

As opposed to writing something like

const error = {something: "something"} /// type => {something: string} for example

I found two work around you can try out, here is the first:

const error = {
      [key]: "error!"
} as ValidationError<S>

That will make the error go away, but you are type-casting here, so you are asserting that is the correct type. Typescript reads this and trusts you.

Second workaround

const error: ValidationError<S> = Object.create({[key]: "error!"})

Here you are no longer casting which is a plus, but you have to use Object.create which isn't as nice as using literals. I think the reason this works is because when creating an object with Object.create and dynamic fields, typescript doesn't evaluate it to type {[x: string]: string}.

To make the second solution a bit nicer, you could write a helper function, something like:

function createValidationError<S>(key: keyof S): ValidationError<S> {
    return Object.create({[key]: "error!"});
}

Then you could just call that directly instead of building the objects in other functions.