Reputation: 3757
Here is an example below and the problem is highlighted in the comments.
function formatObjectValues<T, K extends keyof T>(
obj: T,
formatConfig: {
prop: K;
format: (arg: T[K]) => string;
}[]
) {
return formatConfig.map(({ prop, format }) => {
return format(obj[prop]);
});
}
const obj = { wheels: ["good", "bad", "great", "new"], lights: 2, doors: "new" };
formatObjectValues(obj, [
{
prop: "doors",
format: (doors) => `${doors}`,
// PROBLEM: doors inferred as being string | number | string[] but should only be string
},
{
prop: "wheels",
format: (wheels) => `${wheels}`,
// PROBLEM: wheels inferred as being string | number | string[] but should only be string[]
},
{
prop: "lights",
format: (lights) => `${lights}`,
// PROBLEM: inferred as being string | number | string[] but should only be number
},
]);
How does the type signature of formatObjectValues
need to change to fix the problems mentioned above?
Upvotes: 1
Views: 166
Reputation: 3757
OK I think I got it.
type Formatter<T, K> = K extends Extract<keyof T,string> ? { prop: K, format: (val: T[K]) => string } : never
function formatObjectValues<T,K extends Extract<keyof T, string>>
(
obj: T,
formatConfig: Formatter<T, K>[]
) {
return formatConfig.map(({ prop, format }) => {
return format(obj[prop]);
});
}
const obj = { wheels: ["good", "bad", "great", "new"], lights: 2, doors: "new" };
formatObjectValues(obj, [
{
prop: "doors",
format: (doors) => `${doors}`,
},
{
prop: "wheels",
format: (wheels) => `${wheels}`,
},
{
prop: "lights",
format: (lights) => `${lights}`,
},
]);
Upvotes: 1