I have a TypeScript module where I am importing a specific type and function:
type Attributes = {
[key: string]: number;
};
function Fn<KeysOfAttributes extends string>(opts: { attributes: Attributes }): any {
// ...
}
Unfortunately, I am unable to make any modifications to the code above.
In my own module, I implemented the following code:
// variant 1
const attributes = { // this object is hard coded (not dynamically generated)
foo: 1,
bar: 2,
baz: 3
};
type Type = typeof attributes;
type Keys = keyof Type;
Fn<Keys>({
attributes
});
Everything is functioning perfectly. However, now I want to ensure that the constant attributes
adheres to the Attributes
type, ensuring that the keys are strings and the values are numbers. So, I modify my code as follows:
// variant 2
const attributes: Attributes = {
foo: 1,
bar: 2,
baz: 3
};
type Type = typeof attributes;// equals {[key: string]: number;}
type Keys = keyof Type;// equals string | number. Why ?
Fn<Keys>({// Here, I would like Keys to be "foo" | "bar" | "baz", instead I have string | number
attributes
});
However, when I try to execute the code using the line Fn<Keys>({
, I encounter the following error:
Type 'string | number' does not satisfy the constraint 'string'.
Type 'number' is not assignable to type 'string'.ts(2344)
I am confused as to why the type Keys
ends up being string | number
when the index signature clearly specifies that the key must be a string?
How can I guarantee that the "foo" | "bar" | "baz"
type is passed as a type argument rather than string | number
?
I am satisfied with the first variant, but I am struggling to understand why the second one is causing issues. Any suggestions would be greatly appreciated!
Thank you!