Giter VIP home page Giter VIP logo

Comments (9)

whzx5byb avatar whzx5byb commented on June 22, 2024 1

There's definitely many duplicates of this

#27808, extends oneof issue, I've seen too many of them.

@noahtallen just use the distributive behavior to make it work

function doSomethingWithData<T extends SomeThings>({thing, data}: T extends unknown ? ArgType<T> : never) {
  if (thing === SomeThings.One) {
    console.log(data.x); // OK
  }
}

Note that you also have to make the literal object foo declared as const.
const foo = {thing: SomeThings.One, data: {x: 1}} as const;

from typescript.

noahtallen avatar noahtallen commented on June 22, 2024 1

Hm interesting. It's odd to me that something like T extends T ? ... : never is required to get inference to work, given that T always extends T. So this is basically just tricking/forcing the compiler to distribute here?

Either way, happy that there's a solution!

from typescript.

MartinJohns avatar MartinJohns commented on June 22, 2024

Because within the function the compiler doesn't know which type is passed along. It could be SomeThings.One, it could be SomeThings.Two, it could also be the type SomeThings.One | SomeThings.Two. There's definitely many duplicates of this, just don't have one at hand right now.

from typescript.

noahtallen avatar noahtallen commented on June 22, 2024

The compiler should be able to know that SomeThings.One was passed within this block. It should also be know (based on the contracted specified by the ArgType interface) that it's impossible to pass mismatched arguments where the data doesn't match the enum:

// We know which one was passed now:
  if (thing === SomeThings.One) {
    console.log(data.x);
  }

// Correctly shows an error, so it does narrow the type of `data` based on the enum here:
doSomethingWithData({thing: SomeThings.One, data: {y: 'xyz'});

I think it evaluates ArgType<T> too early into a union of all possible values, where if it evaluated it within the if statement, it should know that it resolves to a single possibility

from typescript.

MartinJohns avatar MartinJohns commented on June 22, 2024

You misunderstand how generics work. Just because thing equals SomeThings.One does not mean you're dealing with a { x: number } data.

This is a perfectly valid and legal call:
doSomethingWithData<SomeThings.One | SomeThings.Two>({ thing: SomeThings.One, data: { y: "abc" }})

from typescript.

noahtallen avatar noahtallen commented on June 22, 2024

That's great, thanks for sharing! looks like as const isn't needed if you do:

const foo: ArgType<SomeThings.One> = {thing: SomeThings.One, data: {x: 1}};

if (someCondition) {
  foo.data.x = 100;
}

// works!
doSomethingWithData(foo);
doSomethingWithData({ thing: SomeThings.Two, data: {y: 'hi'}});

Anyways, I'm curious how this works. Why T extends unknown when T is known?

ts playground

from typescript.

whzx5byb avatar whzx5byb commented on June 22, 2024

Why T extends unknown when T is known?

Because unknown is the top type that anything can be assigned to it, to make sure that the conditional type always get in the "true" branch. You can replace it with T extends any or T extends T, all of them are OK.

And for "distributive" behavior, see https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#distributive-conditional-types.

from typescript.

fatcerberus avatar fatcerberus commented on June 22, 2024

So this is basically just tricking/forcing the compiler to distribute here?

Yes. Conditional types distribute over type parameters, so:

type ArrayOf<T> = T extends T ? T[] : never;
type Test = ArrayOf<string | number>;  // string[] | number[];

whereas without distribution you’d get (string | number)[] instead.

from typescript.

RyanCavanaugh avatar RyanCavanaugh commented on June 22, 2024

#58634 (comment)

from typescript.

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.