简体   繁体   中英

How to check if response is of specific interface type?

I am writing a integration test.

It passes but the only way I know if it passes is by checking if the response type is an object like so:

describe('INTEGRATION test1', () => {
  it('get user from service success', async () => {
    const serviceObj: IFindPropsRequest = {
      find: {
        findMeta: {
          prop1: 'value1',
          prop2: 'Individual',
        }
    };
    const resp: ServiceResponse<IFindResponse> = await findProfileService(serviceObj, 'DE');

    expect(typeof resp).toBe('object'); // want to change this
  });

instead of expect(typeof resp).toBe('object'); I am looking for a way to see if resp is of type IFindResponse

how can I accomplish this?

The short answer is: you can't. interface is something that's removed during runtime, so when your application is running there's no facility to see if an arbitrary incoming object can satisfy a type of interface.

The typescript way of handing this is to write a type guard, but it involves you manually writing the code to see if the incoming type satisfies the interface.

We've solved this by not using typescript. We write JSON-Schema for runtime validation, and actually have scripts that take the JSON-Schema files and convert them to typescript types for static analysis. Not saying that answers your question, but the point here is that you need something that does this at runtime, and Typescript aint it.

The 'crazy hack' is if you get the response, convert it to a .ts file and manually invoke the typescript compiler on the created files... Not sure if this is a road you want to go down.. but it's a possibility.

当 @Max 评论resp instanceof IFindResponse时,您可以期望为

expect(resp instanceof IFindResponse).toBeTruthy();

After reading @Evert answer I approached this in another way:

describe('INTEGRATION test1', () => {
  it('get user from service success', async () => {
    const serviceObj: IFindPropsRequest = {
      find: {
        findMeta: {
          prop1: 'value1',
          prop2: 'Individual',
        }
    };
    const resp: ServiceResponse<IFindResponse> = await findProfileService(serviceObj, 'DE');

    expect(resp.data.customers).toBeTruthy(); check if property exists
  });

I basically just checked if the response had a property that it will only have if the request vent through.

The same solution, but with a typeguard:

describe('INTEGRATION test1', () => {
  it('get user from service success', async () => {
    const serviceObj: IFindPropsRequest = {
      find: {
        findMeta: {
          prop1: 'value1',
          prop2: 'Individual',
        }
    };
    const resp: ServiceResponse<IFindResponse> = await findProfileService(serviceObj, 'DE');

    expect(isIFindResponse(resp)).toBeTruthy();
  });

  function isIFindResponse(input: any): input is IFindResponse {
    return input.data.customers !== undefined;
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM