1

I do have this class:

class Container<T>
{
    prop<K extends keyof T>(key: K): BehaviorSubject<T[K]>
    {
        return null;    // something
    }

    obj<K extends keyof T>(key: K): Container<T[K]>
    {
        return null;    // something
    }
}

And using it like this:

interface Obj
{
    id: number;

    employee: {
        id: number;
        name: string;
    }
}

let container: Container<Obj>;
let id = container.prop('id');  // BehaviorSubject<number>
let employee = container.obj('employee');   // Container<{ id: number; name: string; }
let employeeName = employee.prop('name');   // BehaviorSubject<string>

Now I want the same thing (type of variables commented above) but I'd like to use the same function name for prop and obj. I want a overload that switchs the returned type base on the property type.

Is it possible in TypeScript?

7
  • Can you also provide a code example of how you'd like to use the function (after the two prop and obj functions have been merged)? Commented Dec 29, 2016 at 13:09
  • That will be the job of a class that inspect things dynamically. I want just a way to map this to static types. Commented Dec 29, 2016 at 13:15
  • But both functions expect the same argument, how would you differentiate between the two? Commented Dec 29, 2016 at 14:16
  • The object will be pre-created and the functions will just return the properties. It happens that the pre-created data matches these types that I want. Commented Dec 29, 2016 at 14:22
  • I had submited a feature request to TypeScript to implement a elegant (IMHO) way to do this github.com/Microsoft/TypeScript/issues/13214 Commented Dec 29, 2016 at 14:23

1 Answer 1

1

If I understand you then you can do something like this:

class Container<T> {
    private value: T;

    ...

    get<K extends keyof T>(key: K): Container<T[K]> | BehaviorSubject<T[K]> {
        let value = this.value[key];

        if (typeof value === "number" || typeof value === "string" || typeof value === "boolean") {
            // return a BehaviorSubject
        } else {
            // return a Container
        }
    }
}

The problem will be of course when using this Container.get, you'll need to type assert:

let id = container.get("id") as BehaviorSubject<number>;
let employee = container.obj("employee") as Container<{ id: number; name: string; };
Sign up to request clarification or add additional context in comments.

2 Comments

I want the thing without type asserts nor having extra properties (with intersection types). I tried it with overloaded functions with extra parameters and default values but could not achieve too.
You can not have different signatures if they all have the same exact args (in this case key: K), there's no way around that. And you can't do without the type assertion because the information about which type it is is only available inside the function body. You better just stick with the two methods.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.