Reputation: 1159
How to write type for getIn
method (GetInResult
)?
I want the result
to point to the string
type from the Second.second
interface of the e2
Example
class.
type DataValue = undefined | null | boolean | string | number | bigint | Example<any>;
// DataType can be object or array with primitive values or Example instances
interface DataType {
[key: PropertyKey]: DataValue;
}
type Keys = readonly PropertyKey[];
type GetInResult<T, KS extends Keys> = KS extends [infer F, ...infer R]
? F extends keyof T
? R extends Keys
? T[F] extends Example<infer NestedT>
? NestedT extends DataType
? GetInResult<NestedT, R>
: undefined
: T[F]
: T[F]
: undefined
: undefined;
class Example<T extends DataType> {
#data: T;
constructor(data: T){
this.#data = data;
}
getIn<KS extends Keys, K extends PropertyKey>(keys: KS & K[]): GetInResult<T, KS> {
const key = keys.shift();
if (key && Object.prototype.hasOwnProperty.call(this.#data,key)) {
const value = this.#data[key];
if (keys.length) {
if (value instanceof Example) {
return value.getIn(keys);
}
return undefined;
}
return value; // error: check playground below
}
return undefined;
}
}
interface Second extends DataType {
second: string;
}
const second: Second = {
second: '2'
}
const e2 = new Example(second);
interface First extends DataType {
first: string;
firstNested: Example<Second>;
}
const first: First = {
first:'1',
firstNested: e2
};
const e1 = new Example(first);
const result = e1.getIn(['firstNested','second']);
// result should be a string from Second.second interface because firstNested is pointing to the Example<Second> and second points to Second.second
Upvotes: 0
Views: 168
Reputation: 1159
I made modifications to @myNameIsDu's code and was able to achieve a satisfactory result.
Upvotes: 1
Reputation: 73
Maybe you need this
The difference is that data is not private and requires const assertions
Upvotes: 1