Microsoft/TypeScript

in operator typeguard precision loss

Open

#51,339 opened on Oct 28, 2022

View on GitHub
 (2 comments) (0 reactions) (0 assignees)TypeScript (6,726 forks)batch import
Experience EnhancementHelp WantedSuggestion

Repository metrics

Stars
 (48,455 stars)
PR merge metrics
 (Avg merge 6d 17h) (9 merged PRs in 30d)

Description

Bug Report

🔎 Search Terms

🕗 Version & Regression Information

v4.9.0 v4.9.1 5.0.0-dev.20221101

⏯ Playground Link

Playground link with relevant code

💻 Code

function addressOrThrow(value: unknown) {
  if (typeof value !== "object" || value == null) throw new TypeError();

  if (!("street" in value) || typeof value.street !== "string")
    throw new TypeError();

  if (!("houseNumber" in value) || typeof value.houseNumber !== "number")
    throw new TypeError();

  return value;
}

function addressOrThrowTG(value: unknown): value is Address {
  addressOrThrow(value);
  return true;
}

function personOrThrow(value: unknown) {
  if (typeof value !== "object" || value == null) throw new TypeError();

  if (!("firstName" in value) || typeof value.firstName !== "string")
    throw new TypeError();

  if (!("lastName" in value) || typeof value.lastName !== "string")
    throw new TypeError();

  if ("middleName" in value && typeof value.middleName !== "string")
    throw new TypeError();

  if (!("addresses" in value) || !Array.isArray(value.addresses))
    throw new TypeError();

  if (!value.addresses.every(addressOrThrowTG))
    throw new TypeError();

  return value;
}

type Address = ReturnType<typeof addressOrThrow>;

type Person = ReturnType<typeof personOrThrow>;

🙁 Actual behavior

type Address = object & Record<"street", unknown> & Record<"houseNumber", unknown> type Person = object & Record<"firstName", unknown> & Record<"lastName", unknown> & Record<"addresses", unknown>

🙂 Expected behavior

type Address = object & Record<"street", string> & Record<"houseNumber", number> type Person = object & Record<"firstName", string> & Partial<Record<"middleName", string>> & Record<"lastName", string> & Record<"addresses", Address[]>

Contributor guide