Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic type where one field type is constraint by key name specified in second field

Let's say I have this type

type Form = {
  enabled: true;
  name: string;
};

and I want to make another generic type that represents a change event for a specific field

type ChangeEvent<T> = {
  field: keyof T;
  value: T[keyof T];
};

The example above does not properly constraint value

const e: ChangeEvent<Form> = {
  field: "enabled",
  value: "false", // accepts boolean or string
}

I'm aware of mapped types

type ChangeEvent<T> = {
  [K in keyof T]: T[K];
}

But I want to know how to use this with a separate value field.

I also don't want to specify a second generic argument like

type ChangeEvent<T, K extends keyof T> = {
  field: K;
  value: T[K];
}

How do I fix the first version of ChangeEvent?

like image 980
ErpaDerp Avatar asked Dec 06 '25 03:12

ErpaDerp


1 Answers

I would love if I'm wrong and this isn't the accepted answer, but I am pretty sure the absolute best you can do at present is:

type KChangeEvent<T, K extends keyof T = keyof T> = {
  field: K;
  value: T[K];
}

export type ChangeEvent<T> = KChangeEvent<T>

So it technically has a second type parameter, but the exported type closes over the keyof T default.

But ultimately, K must be named because that's the only way you can get TypeScript to constrain on the same type in more than one place. keyof T doesn't cut it because each reference could be a different type.

like image 151
backtick Avatar answered Dec 08 '25 11:12

backtick



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!