I am trying to create a type safe version of the get lodash function (see here). My idea is to create a function that is able to return the correct type if the nested property is available otherwise undefined.
interface Nested {
value: 'some' | 'type';
}
interface SomeComplexType {
foo: string;
bar: number;
nested: Nested;
}
const testObject: SomeComplexType = {
foo: 'foo value',
bar: 1234,
nested: {
value: 'type'
}
};
// The type of someValue should be: 'some' | 'type'
const someValue = lookup(testObject, 'nested.value');
console.log('Value found:', someValue);
Right now I have the following:
function get<T, K extends keyof T>(object: T, key: K): T[K] | undefined {
return object[key];
}
function lookup<T, K extends keyof T>(object: T, path: string) {
const parts = path.split('.');
const property = parts.shift() as K; // TODO autoinfer is possible?
const value = get(object, property);
if (!parts.length || value === undefined) {
return value;
}
const newPath = parts.join('.');
return lookup(value, newPath);
}
But I am stuck with the lookup return type. Typescript in strict mode says:
src/lookup.ts:14:10 - error TS7023: 'lookup' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.
Any ideas?
Answering my own question after the introduction of template literal types.
Now with template literal types you can obtain exactly what I wanted.
See example in playground.
See here for the implementation (from this tweet): https://github.com/ghoullier/awesome-template-literal-types#dot-notation-string-type-safe