The question is a bit hard to explain without showing an example, so let's look at this Message
type that will be extended and used as base type for other types.
interface Message<E extends string = string, P = any> {
topic: E;
params: P;
}
I have this interface for indicading message type. The topic and parameters are generic to make sure the interface could be extend for different cases like:
interface OrderParams {
userId: string;
orderId: string;
}
interface CreateOrderMessage extends Message<'orders.create', OrderParams> {}
interface UpdateOrderMessage extends Message<'orders.update', OrderParams> {}
...
type CustomMessage = CreateOrderMessage | UpdateOrderMessage | ...;
This allows me to add strict typing for topic
and params
for different topic types which I could use with a class:
class PubSub<T extends Message = Message> {
publish(message: T): void;
subscribe(topic: string): void;
}
If we pass CustomMessage
as a generic type to PubSub<>
it will check typings for publish
method, but I also want to make sure topic
parameter of subscribe
method is also type checked using E
generic type of T extends Message
generic type.
So, is there a way to somehow extract generic type of another generic type so I could write something like below?
subscribe(topic: GenericOf<T, 0>); // 1st generic of T type
subscribe(topic: TypeOfObjectKey<T, 'topic'>); // Type of 'topic' property of T type
CodePudding user response:
subscribe(topic: T['topic'])
will ensure the topic
parameter of subscribe
is the same type as the topic
property of the interface passed into the generic. Here's an example derived from the code you've provided in your question (I've made it error so that the underlying type is easily visible):
interface Message<E extends string = string, P = any> {
topic: E;
params: P;
}
interface OrderParams {
userId: string;
orderId: string;
}
interface CreateOrderMessage extends Message<'orders.create', OrderParams> {}
interface UpdateOrderMessage extends Message<'orders.update', OrderParams> {}
type CustomMessage = CreateOrderMessage | UpdateOrderMessage;
class PubSub<T extends Message = Message> {
publish(message: T): void {};
subscribe(topic: T['topic']): void {};
}
new PubSub<CustomMessage>().subscribe('')
^^
Argument of type '""' is not assignable to parameter of type '"orders.create" | "orders.update"'.