Skip to content

in operator typeguard precision loss #51339

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
santa-trout opened this issue Oct 28, 2022 · 2 comments
Open

in operator typeguard precision loss #51339

santa-trout opened this issue Oct 28, 2022 · 2 comments
Labels
Experience Enhancement Noncontroversial enhancements Help Wanted You can do this Suggestion An idea for TypeScript

Comments

@santa-trout
Copy link

santa-trout commented Oct 28, 2022

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[]>

@RyanCavanaugh RyanCavanaugh added Suggestion An idea for TypeScript Help Wanted You can do this Experience Enhancement Noncontroversial enhancements labels Oct 28, 2022
@RyanCavanaugh
Copy link
Member

@ahejlsberg any easy way to make this happen?

@arahansen
Copy link

Also just ran into this. Here is a playground reproducing the issue.

The above errors in version 4.9.3 but no error in 4.8.4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Experience Enhancement Noncontroversial enhancements Help Wanted You can do this Suggestion An idea for TypeScript
Projects
None yet
Development

No branches or pull requests

3 participants