Typescript IReturn<T> has non-optional createResponse()

Hi, since upgrading to 4.5.6, when I update Typescript reference, IReturn now has a non optional createResponse method. This breaks any autoQuery consuming code. I can comment, but it will obviously re-appear as I add more dtos so can you make optional?

interface IReturn<T>
{
    createResponse() : T;
}

It’s needed as TypeScript wont be able to tell if a Type implements the interface and what it should return without it.

What do you mean by it breaks “autoQuery consuming code”? Can you provide the generated DTOs that it breaks?

Yes, found the same here after upgrading. Our code broke, we can’t create objects (body) like this anymore. see example.

interface ChangeEmailAddress extends IReturn<ChangeEmailAddressResponse>
{
    emailAddress?: string;
}
interface ChangeEmailAddressResponse
{
    responseStatus?: ResponseStatus;
}

...

	setEmail(emailAddress: string) {
        let body: ServiceModels.ChangeEmailAddress = {
			emailAddress
		};

		return this.$http
            .put<ServiceModels.ChangeEmailAddressResponse>(`${this.globalVariables.baseApiUrl}/user/emailAddress`, body);
		
	}

Sorry for delay, didn’t see response.

I use AutoQuery DTOs in Typescript:

 [Route("/api/contracts")]
public class QueryContracts : QueryDb<Contract>
{
    public long? AccountId { get; set; }
    public bool? IsOpen { get; set; }
    public bool Deleted => false;
}

This DTO is exposed when you generate typescript reference, so in typescript I can say:

let request: dtos.QueryContracts = { accountId: 1234 }

and post this to the server and all is great.

But as QueryDb<T> implements IReturn<QueryResponse<T>> the typescript declaration for QueryContracts now needs createResponse to be implemented.

It doesn’t sound like you’re using these TypeScript definitions with the TypeScript servicestack-client as normally you’d be using the concrete types so your request would be:

let request = new dtos.QueryContracts();
request.accountId = 1234;

Having to specify the generic type response defeats the purpose of the IReturn<T> marker which should allow TypeScript to refer the Response Type and let you write:

client.put(request)
    .then(r => { //Typed Response
     });

Which is why we need createResponse() on IReturn<T> so TypeScript can infer what the Response Type is, implementing an empty IReturn<T> interface isn’t enough.

But as it looks like you want to use the TypeScript interfaces for different HTTP Clients I’ve removed them from being emitted in ambient Type Declarations in this commit so the IReturn interfaces revert to empty marker interfaces:

interface IReturnVoid
{
}

interface IReturn<T>
{
}

This change is available from v4.5.7+ that’s now available on MyGet.

But as they don’t implement createResponse/getTypeName these interfaces aren’t enough to call Services on their own, so I’ve added support for being able to use TypeScript JsonServiceClient with a url and optional args in v0.0.23 of npm servicestack-client which will let you use call services with the path info and anon object, e.g:

let request: dtos.QueryContracts = { accountId: 1234 };

client.get<dtos.QueryResponse<dtos.Contract>>("/api/contracts", request)
    .then(r => { //typed response
    });

But if you’re going to use the TypeScript JsonServiceClient I’d recommend using the default concrete DTO classes instead (i.e /types/typescript) so you can get a nice development experience, e.g:

let request = new dtos.QueryContracts();
request.accountId = 1234;

client.get(request)
    .then(r => { //typed response
    });

Example using implicit conventions:

let request = new dtos.QueryContracts();
request.accountId = 1234;

client.get(request, { AmountGreaterThan: 1000 })
    .then(r => { //typed response
    });

great - makes complete sense; yes I’m using restangular. I will take a look at the ts client when i have some time.