Robert Koritnik
Robert Koritnik

Reputation: 105071

One type definition to cover properties of primitive and generic types without unioning

This is the pattern that requires me to define two types that I would like to refactor/consolidate:

...
.then((result1: any) => {
    let promises = {
       one: $q.when(val1),
       two: $q.when(val2)
    };
    return $q.all(promises);
})
.then((resolvedPromises: any) => {
    // use
    resolvedPromises.one...
    resolvedPromises.two
});

I would like to define type of promises and resolvedPromises but as they are type related I would like to define a single type (likely generic) instead of defining two types with similar definition.

So instead of:

public interface ResultingType {
    [id: string]: any,
    one: Something1,
    two: Something1
}

public interface PromisingType {
    [id: string]: ng.IPromise<any>,
    one: ng.IPromise<Something1>,
    two: ng.IPromise<Something2>
}

The problem is that from the usual generic type perspective we provide the inner-most type to be injected into, but in my case I need to somehow define the outer type either being ng.IPromise<> or nothing actually.

I also don't want to end up with a single type that would allow both types:

public interface ConsolidatedType {
    [id: string]: any | ng.IPromise<any>,
    one: Something1 | ng.IPromise<Something1>,
    two: Something2 | ng.IPromise<Something2>
}

This would allow for mixing and matching in invalid places. So that's a no-go. Is there any other way to actually have a single type without code repetition that only wraps types into promises?

Upvotes: 3

Views: 59

Answers (1)

Nitzan Tomer
Nitzan Tomer

Reputation: 164367

How about:

interface BaseType<T, S> {
    [id: string]: T;
    one: S;
    two: S;
}

And then:

...
.then((result1: any) => {
    let promises = {
       one: $q.when(val1),
       two: $q.when(val2)
    } as BaseType<ng.IPromise<any>, ng.IPromise<Something1>>;
    return $q.all(promises);
})
.then((resolvedPromises: BaseType<any, Something1>) => {
    // use
    resolvedPromises.one...
    resolvedPromises.two
});

You can also create "shortcuts":

interface PromiseType extends BaseType<ng.IPromise<any>, ng.IPromise<Something1>> {}

interface ValueType extends BaseType<any, Something1> {}

And then:

...
.then((result1: any) => {
    let promises = {
       one: $q.when(val1),
       two: $q.when(val2)
    } as PromiseType;
    return $q.all(promises);
})
.then((resolvedPromises: ValueType) => {
    // use
    resolvedPromises.one...
    resolvedPromises.two
});

Upvotes: 1

Related Questions