I just checked the Object.entries() typing:
/**
* Returns an array of key/values of the enumerable properties of an object
* @param o Object that contains the properties and methods. This can be an object that you created or an existing Document Object Model (DOM) object.
*/
entries<T>(o: { [s: string]: T } | ArrayLike<T>): [string, T][];
Option 1
It appears, you can pass the value argument type to Object.entries() explicitly. This way it regonizes the typings
const filterOptions = <T extends string>(
options: Record<T, Option>,
) => {
return Object.entries<Option>(options) // added option type here!
.map(([key, entry]) => ({
key,
...entry, // It knows for sure now..
}))
.filter(() => {
// do filtering stuff...
});
}
Option 2
The Record typings make use of symbols / numbers and strings as keys.
/**
* Construct a type with a set of properties K of type T
*/
type Record<K extends keyof any, T> = {
[P in K]: T;
};
For example, this does work:
const d = Symbol('somedescripton')
const a: Record<string, Option> = {
'a': {name: 'strrst'},
b: {name:'sdfsdf'},
0: {name: 'srfsdfds'},
d: {name: 'sdfsdfd'}
}
The Object.entries() will convert it to string keys but it accepts still, Symbols and numbers aswell!!^
So for having a Record type with only string keys you would have it to type yourself for being able to omit the explicit casting:
type StringRecord<T extends string, K> = {[key in keyof T]: K }
const filterOptions = <T extends string>(
options: StringRecord<T, Option>,
) => {
return Object.entries(options)
.map(([key, entry]) => ({
key,
...entry, // works now..
}))
.filter(() => {
// do filtering stuff...
});
}
Object.entrieswith explicit generic argument like here: tsplay.dev/mMVjzW . Let me know if it wirks for youT? It only occurs in one parameter and not the return type, so your function would have essentially the same signature if you just deleted it and replaced it withstring.