Consider the following interface along with an object that implements it:
interface IData {
a: TypeA;
b: TypeB;
c: boolean;
d: string;
}
const myObject: { data: IData } = {
data: {
a: valueA,
b: valueB,
c: true,
d: "valueD"
}
}
Now, I want to create a function that retrieves a single property from this object and automatically infers its return type:
function getProperty(obj: { data: IData }, field: keyof IData){
return obj.data[field];
}
const myStringField = getProperty(myObject, "d"); // should be of type string
const myBoolField = getProperty(myObject, "c"); // should be of type boolean
How can we define the getProperty
function so that it correctly infers the return types instead of TypeA | TypeB | boolean | string
?
Here is another example involving more complex scenarios:
interface IValue<T> {
value?: T;
}
interface IData2 {
a?: IValue<string>;
b?: IValue<number>;
c?: IValue<boolean>;
d?: IValue<string>;
}
function getPropertyValue<T extends keyof IData2>(field: T, data: IData2) {
return data[field] ? data[field]!.value : undefined; // The '!' indicator is necessary for compilation
}
const sampleData: IData2 = {
a: { value: 'a' },
b: { value: 2 },
c: { value: false },
};
const value1 = getPropertyValue('a', sampleData); // expecting type `string`
const value2 = getPropertyValue('b', sampleData); // expecting type `number`
const value3 = getPropertyValue('b', sampleData); // expecting type `boolean`
const value4 = getPropertyValue('b', sampleData); // expecting type `undefined`