Reputation: 189
declare type Foo = {
fieldA?: 'a' | 'b' | 'c';
fieldB?: SomeOtherType;
fieldC?: number;
fieldD?: string;
fieldE?: boolean;
}
declare type Bar = {
fieldX?: boolean;
fieldY?: 'hello' | 'world'
fieldZ?: AndYetAnotherType;
}
const getPropertyFromFooOrBar = (
property: string,
foo: Foo,
bar: Bar
): MISSING_TYPE => {
return foo[property] || bar[property] || undefined;
};
I need the return type of the function (MISSING_TYPE
above) to be a value from Foo
or Bar
(or undefined
). Is there something similar to keyof Bar
that can be used to handle this typing?
Upvotes: 0
Views: 40
Reputation: 189
I ended up going with the following:
declare type Foo = {
fieldA?: 'a' | 'b' | 'c';
fieldB?: SomeOtherType;
fieldC?: number;
fieldD?: string;
fieldE?: boolean;
}
declare type Bar = {
fieldX?: boolean;
fieldY?: 'hello' | 'world'
fieldZ?: AndYetAnotherType;
}
type FooValue = Foo[keyof Foo];
type BarValue = Bar[keyof Bar];
const getPropertyFromFooOrBar = (
property: string,
foo: Foo,
bar: Bar
): FooValue | BarValue | undefined => {
return foo[property] || bar[property] || undefined;
};
Upvotes: 0
Reputation: 20494
You can determine the type of a property of combined types by creating a union type and using keyof that union type in a generic type declaration. That's a confusing sentence - here are the steps taken in the example below:
type FooAndBar = Foo & Bar;
const getPropertyFromFooOrBar = <T extends keyof FooAndBar>(
property: T,
foo: Foo,
bar: Bar
): FooAndBar[T] | undefined => {
return { ...foo, ... bar }[property];
};
getPropertyFromFooOrBar('fieldA', { fieldA: 'a' }, { fieldY: 'hello' });
// getPropertyFromFooOrBar: <"fieldA">(property: "fieldA", foo: Foo, bar: Bar) => "a" | "b" | "c"
Upvotes: 1