Skip to content

Incorrect return types, non-discriminated unions and types not exported #204

@shrink

Description

@shrink

I'm using the Vercel SDK for the first time and encountering missing types, non-discriminated unions and incorrect types. As I understand it, this SDK is generated by @speakeasy-api (cc @simplesagar) so I am not sure if the issue is with Speakeasy or with Vercel.

  1. The types for some endpoints are wrong. I did a quick check of the first ~1/3rd of documented endpoints and found these examples of incorrect response information (which in turn means the SDK is wrong).

For example, dns.getRecords:

const records = await vercel.dns.getRecords({
  domain: "example.com"
})

TypeScript believes records to be a string:

export type GetRecordsResponseBody =
  | ResponseBody3
  | GetRecordsResponseBody2
  | string;

My current workaround is to combine ReturnType and Exclude:

await vercel.dns.getRecords({
  domain: "example.com"
}) as Exclude<Awaited<ReturnType<typeof vercel.dns.getRecords>>, string>;
  1. Types are not exported. For example, Creates a webhook:
await vercel.webhooks.createWebhook({
  teamId: "team_1a2b3c4d5e6f7g8h9i0j1k2l",
  slug: "my-team-url-slug",
  requestBody: {
    url: "https://experienced-sailor.biz/",
    events: [
      "deployment.cleanup",
    ],
  },
})

Although requestBody is of type CreateWebhookRequestBody it isn't possible to import CreateWebhookRequestBody because it isn't exported. The workaround to access the type for requestBody is to do something like this (which is quite fragile):

Parameters<typeof vercel.webhooks.createWebhook>[0]['requestBody'];

The same is true of return types. The workaround is:

ReturnType<typeof vercel.dns.getRecords>
  1. The return type unions aren't discriminated. DNS records, for example, can be one of many types (A CNAME MX etc.). The type mxPriority only exists on an MX record so it should be possible to do something like if record.type === "MX" then record.mxPriority... but because type is the record type enum, it isn't possible.
/**
 * The type of record, it could be one of the valid DNS records.
 */
export const CreateRecordRequestBodyDnsRequest6Type = {
  A: "A",
  Aaaa: "AAAA",
  Alias: "ALIAS",
  Caa: "CAA",
  Cname: "CNAME",
  Https: "HTTPS",
  Mx: "MX",
  Srv: "SRV",
  Txt: "TXT",
  Ns: "NS",
} as const;
/**
 * The type of record, it could be one of the valid DNS records.
 */
export type CreateRecordRequestBodyDnsRequest6Type = ClosedEnum<
  typeof CreateRecordRequestBodyDnsRequest6Type
>;

export type RequestBody6 = {
  /**
   * A subdomain name or an empty string for the root domain.
   */
  name: string;
  /**
   * The type of record, it could be one of the valid DNS records.
   */
  type: CreateRecordRequestBodyDnsRequest6Type;
  /**
   * The TTL value. Must be a number between 60 and 2147483647. Default value is 60.
   */
  ttl?: number | undefined;
  /**
   * An MX record specifying the mail server responsible for accepting messages on behalf of the domain name.
   */
  value: string;
  mxPriority: number;
  /**
   * A comment to add context on what this DNS record is for
   */
  comment?: string | undefined;
};

I haven't yet identified a reliable workaround for the lack of discrimination.

Thank you :)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions