Reputation: 182
I have two generic types - Client<T>
and MockClient<T>
. I would like to describe a third generic type - Mocked<C extends Client>
- which should be the specialization of MockClient
corresponding to a given specialization of Client
. For example:
type PersonClient = Client<Person>;
// the following two types should be equivalent
type MockPersonClient = Mocked<PersonClient>;
type MockPersonClient = MockClient<Person>;
In other words, I would like to declare a type like:
type Mocked<C extends Client<T>> = MockClient<T>;
Is it possible to do this in Typescript? If not, is there a proposal for it (I have no idea how this feature would be called), or is what I am describing ill-defined or fundamentally difficult to implement in a type system?
Upvotes: 0
Views: 73
Reputation: 327964
I think what you want is fairly well-defined, but not currently available in TypeScript (as of v2.5). One feature which would get you there is type-level function application or the more general extended typeof
operator. I'm not sure when, if ever, these features will make it into TypeScript.
There are workarounds. One that I've used, which you figured out from my comment, is to augment your Client<T>
type with a superfluous/phantom property of type T
. Assuming Client<T>
is a class, you could do something like:
class Client<T> {
// phantom property
_clientType: T = void 0 as any;
// rest of class definition
}
type Mocked<C extends Client<{}>> = MockClient<C['_clientType']>
Yes, it has to be a public property, but you can just give it a name that indicates it is for internal use (leading underscore). At runtime it will just be undefined and no user of Client
needs to pay attention to it. (It's a little more complicated if Client
is an interface you want to create an instance from an object literal, because TypeScript will complain that there's no _clientType
property.)
It's up to you if it's worth doing that to your class. Other folks may well have different workarounds to suggest. Good luck!
Upvotes: 1