Skip to content
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

Tagged enum inference with string literal types isn't sophisticated enough #20

Closed
sophiebits opened this issue Nov 18, 2014 · 11 comments
Closed
Assignees

Comments

@sophiebits
Copy link
Contributor

Ideally this would type-check

/* @flow */

type T =
    {type: "a"; a: number} |
    {type: "b"; b: string};

function foo(x: T): string {
    if (x.type === "a") {
        return "" + x.a;
    } else {  // or else if (x.type === "b")
        return x.b;
    }
}

but it gives

test.js:9:21,23: property a
Property not found in
  test.js:5:5,26: object type

test.js:11:16,18: property b
Property not found in
  test.js:4:5,26: object type

(Let me know if I'm just misunderstanding how string types work.)

@sophiebits sophiebits changed the title Tagged enum inference with string types isn't sophisticated enough Tagged enum inference with string literal types isn't sophisticated enough Nov 18, 2014
@avikchaudhuri
Copy link
Contributor

This is an interesting use of string types. Will try supporting it. Basically it may boil down to us not being sensitive to === with string types, in which case the fix should be easy.

@sophiebits
Copy link
Contributor Author

Curious: what's the intended use of string types?

@gabelevi
Copy link
Contributor

Method overloading is the reason I most often hear. Like this example from the TypeScript Language Spec

interface Document {
  createElement(tagName: "div"): HTMLDivElement;
  createElement(tagName: "span"): HTMLSpanElement;
  createElement(tagName: "canvas"): HTMLCanvasElement;
  createElement(tagName: string): HTMLElement;
}

@RReverser
Copy link

+1 for this

@samwgoldman
Copy link
Member

I've been thinking about this issue and I think I have an idea for how to implement this.

When x.type is refined, we install a refinement into the scope called $REFI x.type. We should be able to deconstruct that string to get the original identifier, x. Once we have that, we can look up the type of that var and if it is a UnionT, we can filter the list of types to be only those which are compatible with $REFI x.type and install another refinement on x itself using the filtered UnionT.

That doesn't help us if the type property is pulled off the x object then checked by itself, because we "forget" that the value of type is associated with the object x, I believe.

I know that implementation is pretty wild (string manipulation! yuck!) and its incompleteness is pretty lame too. Worth doing? Is there a better way?

@avikchaudhuri
Copy link
Contributor

@spicyj Finally got around to fixing this, motivated by real-world use cases. We can now write ML in JS! ;)

@sophiebits
Copy link
Contributor Author

Sweeet.

@samwgoldman
Copy link
Member

Fixed in 0.13!

@RReverser
Copy link

@samwgoldman Thanks! Any plans for blog article with examples from the team?

@avikchaudhuri
Copy link
Contributor

Blog post coming soon.

On Tuesday, June 30, 2015, Ingvar Stepanyan notifications@github.com
wrote:

@samwgoldman https://github.com/samwgoldman Thanks! Any plans for blog
article with examples from the team?


Reply to this email directly or view it on GitHub
#20 (comment).

@RReverser
Copy link

Thanks!

jeffmo pushed a commit to jeffmo/flow that referenced this issue Jul 31, 2015
Add friendlier error for two adjacent elements
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants