Given the following example code:
interface Foo {
name: string;
age: number;
}
const foo: Foo = { name: 'lorem', age: 123 };
const useObject = <T>(obj: T) => {
const getValue = (key: keyof T): [RETURN HERE] => {
return obj[key];
}
return { getValue };
}
const { getValue } = useObject<Foo>(foo);
getValue('name');
What would I need to replace [RETURN HERE]
with to give an accurate return type? For example, the type of getValue('name')
would be string
and the type of getValue('age')
would be number
.
CodePudding user response:
Use a generic to "store" what key
is, then use it in the return type:
const getValue = <K extends keyof T>(key: K): T[K] => {
return obj[key];
};
And as @AluanHaddad points out, for this case you don't actually need the return type to be explicitly annotated:
// automatically inferred to return T[K]
const getValue = <K extends keyof T>(key: K) => {
CodePudding user response:
It will not be enough to just paste the return type, because keyof T
is not strict enough to infer the type of value based on the key.
interface Foo {
name: string;
age: number;
}
const foo: Foo = { name: 'lorem', age: 123 };
const useObject = <T,>(obj: T) => {
const getValue = <K extends keyof T>(key: K): T[K] => {
return obj[key];
}
return { getValue };
}
const { getValue } = useObject<Foo>(foo);
getValue('name');
CodePudding user response:
You can introduce a generic type K
for the function getValue
which only allows keys of T
to be passed to the function. Afterwards return the type T[K]
.
const useObject = <T,>(obj: T) => {
const getValue = <K extends keyof T>(key: K): T[K] => {
return obj[key];
}
return { getValue };
}