Given a type and variable:
type Form = {
controls: {
[key: string]: any;
}
}
const form: Form = {
controls: {
firstName: {},
lastName: {},
},
};
I want to create a type which is an object containing all keys of form.controls
with a value type of string
ie:
const formControlsWithStrings = {
firstName: 'foo',
lastName: 'bar',
};
I have tried this:
type FormControlsWithStrings<T extends Form> =
{ [key in keyof T['controls']] : string }
however if I use it to type formControlsWithStrings
above, it enforces the string
value type, but not that the keys are equivalent -it does not require all keys to be present, and I can add new keys.
Why doesn't this work, and how can I get it to work?
Thanks
Stackblitz: https://stackblitz.com/edit/typescript-sxvspk?file=index.ts
CodePudding user response:
That's because the type of form
is Form
which allows for any string
key.
If you let TS
infer the type for form
then it's gonna work as expected:
type Form = {
controls: {
[key: string]: any;
};
};
const form = {
controls: {
firstName: {},
lastName: {},
},
};
type FormControlsWithStrings<T extends Form> = {
[key in keyof T['controls']]: string;
};
const formControlsWithStrings: FormControlsWithStrings<typeof form> = {
firstName: 'abc',
// lastName: 'def' // should not compile when commmented as it a key of form
foo: 'bar', // should not compile as it is not present in form variable
};