Robin
Robin

Reputation: 8498

How to type a generic function, which is based on the extended generic type of the first parameters type?

I've the following definitions:

class RESTClient<E extends { id: number }> extends Client {}
class ParticipantClient extends RESTClient<Participant> {}
const createRESTRequestAction = <E extends { id: number }>(client: RESTClient<E>, value?: E) => {};

Unfortunately the createRESTRequestAction is not typing itself as I want. When I use the following call ..

createRESTRequestAction(ParticipantClient, someRecord);

.. TypeScript expects someRecord to be of type { id: number }. I would like that it expect E to be of type Participant in this case. How can this be achieved?

Is it possible to infer the generic type of the extended RESTClient?

Thank you in advance!

Upvotes: 0

Views: 27

Answers (1)

Zakk L.
Zakk L.

Reputation: 208

The function its self is generic in this case. You are missing the type parameter when invoking your function. Invoke it like: createRESTRequestAction<Participant>(ParticipantClient, someRecord);

Here is a working example (slightly cleaned up):

class RestObject {
    id: number
}

class Participant extends RestObject {
    name: string;
}

class RESTClient<E extends RestObject> {}
class ParticipantClient extends RESTClient<Participant> {}
const createRESTRequestAction = <T extends RestObject>(client: RESTClient<T>, value?: T) => {};

const participantClient = new ParticipantClient();

const anyObj = {};

const otherRestObject = {
    id: 1
}

const participant: Participant = {
    id: 10,
    name: 'Robin'
}

createRESTRequestAction<Participant>(participantClient, anyObj); // TypeError, {} not assignable to Participant

createRESTRequestAction<Participant>(participantClient, otherRestObject); // TypeError, "Name" property is missing in otherRestObject parameter

createRESTRequestAction(participantClient, otherRestObject); // Works, transpiler expects the second object to extend RestObject

createRESTRequestAction<Participant>(participantClient, participant); // Works!

Upvotes: 2

Related Questions