Reputation: 89
How to implement a function which takes an object(part of a union) with path and returns value of the config
object for given path?
I'm trying the following:
type Foo = {
config: {
a: string;
};
};
type Bar = {
config: {
b: string;
};
};
type Baz = Foo | Bar;
const prop = <T extends Baz>(obj: T, path: keyof T["config"]) => {
// I'm getting an error at this point:
// "Type 'keyof T["config"] cannot be used to index type '{ a: string; } | { b: string }'
return obj.config[path];
};
However, if I implement the similar function and trying to access fields at the root level(instead of the config
object), it works smoothly:
type Foo = {
a: string
}
type Bar = {
b: string
}
type Baz = Foo | Bar
const prop = <T extends Baz>(obj: T, path: keyof T) => {
return obj[path]
}
I'm assuming it has something with applying keyof
on the object field of a Union type, but can not quite understand why.
Upvotes: 0
Views: 168
Reputation: 8370
You may rewrite your function as:
const prop = (obj: Baz, path: keyof Baz["config"]) => {
return obj.config[path];
};
or:
const prop = <T, K extends keyof T>(obj: { config: T }, path: K) => {
return obj['config'][path];
};
As for the failure to index type with keyof T["config"]
, it looks like that's a design limitation.
Upvotes: 1
Reputation: 1540
It's not exactly perfect, but this seems to accomplish what you are looking for in my testing:
const prop = <T extends Baz, K extends keyof T['config']>(obj: T, path: K): T['config'][K] => {
return (obj['config'] as T['config'])[path];
};
I tested by running this:
const p = prop({ config: { b: 'hi' } }, 'b');
console.log(p);
Which output hi
.
Upvotes: 1