GithubHelp home page GithubHelp logo

Comments (9)

m-rutter avatar m-rutter commented on May 21, 2024 1

@gvergnaud

Would you be interested in having a look at why this is a case and opening a PR if you find a way to fix it? It would be amazing to have more contributors than just myself on this project :) I would be happy to walk you through the code if you are interested and if you need some help

I think you might have already beat me to it, but thanks for the offer! I do want to look into the internals of ts-pattern if only to improve my type level programming, but also maybe to contribute a bit.

That's really odd, because the result of BrandedId extends object and BrandedId extends BuiltInObjects are consistent between 4.2 and 4.3. We should maybe fill a bug report on the latest typescript version?

Yeah, if I had to guess from your investigation findings this is a typescript regression. We should probably open an issue or search for an existing issue on the typescript issue tracker. The fact that this was introduced sometime between 4.3-beta and 4.3.2 and its not reported as a breaking change makes me think this wasn't an intentional breaking change. Branded types/new type patterns do kinda feel like a second class citizen in typescript and a bit hacky, so its not too surprising that they might have missed it.

@m-rutter I made a quick fix and released it in v3.1.7. Please, tell me if that works as expected on your project

Yep, that fixes it, but I still think its best to raise this upstream. If you want I can try searching for a relevant issue to link here, or create a new one.

from ts-pattern.

m-rutter avatar m-rutter commented on May 21, 2024

If you change the type of id from BrandedId to string, it works in both 4.2 and 4.3 and 4.4-nightly

from ts-pattern.

gvergnaud avatar gvergnaud commented on May 21, 2024

Thanks for the report! I had a quick look and it looks like ExtractPreciseValue doesn't return the correct type in this specific case anymore:

type inverted = InvertPattern<{
  fooBar: { type: 'foo' };
  fooBarId: GuardPattern<BrandedId, BrandedId>;
}>;
// inverted: { fooBar: { type: 'foo' }; fooBarId: BrandedId }. This is correct

type t = ExtractPreciseValue<State, inverted>;
// t: never :(

// Here is the test case that should pass:
type cases = [
  Expect<
    Equal<
      t,
      {
        fooBar: {
          type: 'foo';
          id: BrandedId;
          value: string;
        };
        fooBarId: BrandedId;
      }
    >
  >
];

Would you be interested in having a look at why this is a case and opening a PR if you find a way to fix it? It would be amazing to have more contributors than just myself on this project :) I would be happy to walk you through the code if you are interested and if you need some help

from ts-pattern.

gvergnaud avatar gvergnaud commented on May 21, 2024

I investigated a bit more on this issue and it looks like IsPlainObject<BrandedId> returns different results in 4.2 and in 4.3.

type BrandedId = string & { __brand: 'brandId' };

type BuiltInObjects =
  | Function
  | Error
  | Date
  | RegExp
  | Generator
  | { readonly [Symbol.toStringTag]: string };

export type IsPlainObject<o> = o extends object
  ? o extends BuiltInObjects
    ? false
    : true
  : false;

type x = IsPlainObject<BrandedId> // true in 4.4 and 4.3, false in 4.2 and 4.3-betas

4.2 Playground

4.4 beta Playground

That's really odd, because the result of BrandedId extends object and BrandedId extends BuiltInObjects are consistent between 4.2 and 4.3. We should maybe fill a bug report on the latest typescript version?

from ts-pattern.

gvergnaud avatar gvergnaud commented on May 21, 2024

@m-rutter I made a quick fix and released it in v3.1.7. Please, tell me if that works as expected on your project

from ts-pattern.

m-rutter avatar m-rutter commented on May 21, 2024

@gvergnaud reported it here: microsoft/TypeScript#44353

from ts-pattern.

m-rutter avatar m-rutter commented on May 21, 2024

@gvergnaud

I've been staring at the examples you provided, and I cannot help to conclude that it should be evaluating to true, and that false was a bug in 4.3-beta and earlier. Am I going crazy?

If BrandedId extends BuiltInObjects is false in all versions, then that means the inner ternary of IsPlainObject should go to the else branch, and thus evaluate to true

Am I going insane?

from ts-pattern.

gvergnaud avatar gvergnaud commented on May 21, 2024

No you are not! I think you are right, that was my conclusion too ;) That's why I ended up changing the code of ts-pattern rather than opening an issue on the TS repo. I think it's still a good thing that you opened this issue because it's better to let them know about this weird case and that it was broken in the previous versions.

from ts-pattern.

m-rutter avatar m-rutter commented on May 21, 2024

Maybe as a proper fix there should be some kind of guard for branded primitives.

from ts-pattern.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.