I have an object that contains all the keys that should be valid in a new object I need to make with some modifications to the values of said keys.
Example:
// This object contains all the keys i want to use in a different object below -> "one" and "two".
const myObject: { [id: string]: string } = {
one: 'foo',
two: 'bar',
};
This is how I've tried to extract the keys:
type MyType = {
[T in keyof typeof myObject]: {
bar: string
};
}
If I hover over MyType
in VSCode i see this:
type MyType = {
[x: string]: {
bar: string;
};
}
This is obviously wrong, as it should not accept any string, but the set of keys defined in myObject
.
And this is how I've tried to use the new type:
const test: MyType = {
one: {
bar: 'foo'
},
two: {
bar: 'string'
},
shouldNotBeValid: {
bar: 'foo'
}
}
The key "shouldNotBeValid" shouldn't be allowed, but it still passes. However, if I remove the typing of myObject
, so it's like this:
const myObject = {
one: 'foo',
two: 'bar',
};
and then hover over MyType
I get this which is correct:
type MyType = {
one: {
bar: string;
};
two: {
bar: string;
};
}
Is it possible to express MyType
how I want, and still be able to keep typing of myObject
?
CodePudding user response:
You would have to use a generic function to create the myObject
variable. The generic function will constrain the type to Record<string, string>
but also return the original type of the object.
const myObject = createMyObject({
one: 'foo',
two: 'bar',
})
function createMyObject<T extends Record<string, string>>(obj: T) {
return obj
}
type MyType = {
[T in keyof typeof myObject]: {
bar: string
};
}
// type MyType = {
// one: {
// bar: string;
// };
// two: {
// bar: string;
// };
// }