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

Casting to a subtype / force cast #1898

Closed
STRML opened this issue Jun 6, 2016 · 12 comments
Closed

Casting to a subtype / force cast #1898

STRML opened this issue Jun 6, 2016 · 12 comments

Comments

@STRML
Copy link
Contributor

STRML commented Jun 6, 2016

When the built-in declarations are incorrect and/or missing functions, it would be really helpful to be able to force a cast. For example:

let event = document.createEvent('MouseEvents');
event.initMouseEvent('mouseup', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
foo(event);

function foo(e: MouseEvent) {
  //...
}

This throws the errors:

$ flow check-contents < foo.js
-:1
  1: let event = document.createEvent('MouseEvents');
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call of method `createEvent`
  3: foo(event);
         ^^^^^ Event. This type is incompatible with
  5: function foo(e: MouseEvent) {
                     ^^^^^^^^^^ MouseEvent

-:2
  2: event.initMouseEvent('mouseup', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
           ^^^^^^^^^^^^^^ property `initMouseEvent`. Property not found in
  2: event.initMouseEvent('mouseup', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
     ^^^^^ Event

I need a way to cast Event to MouseEvent, as I know (but Flow does not) that the return type of document.createEvent('MouseEvents') is MouseEvent.

This is also related to #396 as this would be fixable with an easy way to extend built-in types.

@STRML STRML changed the title Casting to a subtype Casting to a subtype / force cast Jun 6, 2016
@vkurchatkin
Copy link
Contributor

vkurchatkin commented Jun 6, 2016

Try this:

function foo(e_: any) {
  const e: MouseEvent = e_;
}

In general you can use this pattern for force-casting:

const foo: number = (('foo': any): number)

@STRML
Copy link
Contributor Author

STRML commented Jun 6, 2016

That's pretty brutal, but the second option works. We really could use some official syntax for this.

STRML added a commit to react-grid-layout/react-draggable that referenced this issue Jun 6, 2016
@phpnode
Copy link
Contributor

phpnode commented Nov 7, 2016

I run into this all the time, it would be nice if there was something like (e: $Cast<MouseEvent>) => {} which could just be a short hand for @vkurchatkin's workaround.

@STRML
Copy link
Contributor Author

STRML commented Nov 7, 2016

Yeah, this would be hugely useful for e.g. screwing with e.target, which 99% of the time is a Node, not just an EventTarget.

@vkurchatkin
Copy link
Contributor

IMO it's a good thing that it looks ugly and stands out

@phpnode
Copy link
Contributor

phpnode commented Nov 7, 2016

$DangerouslyUnsoundCast<MouseEvent> 😄

@phpnode
Copy link
Contributor

phpnode commented Nov 7, 2016

@vkurchatkin I see where you're coming from but it's so common, especially when dealing with React that it does warrant a suitably scarily named shortcut IMHO. In my experience people just use any without recasting when confronted with this kind of issue, and that's worse.

@vkurchatkin
Copy link
Contributor

Well, maybe. For me any is scary enough. Probably it's worth improving coverage command and encouraging people to use it

@mosesoak
Copy link

mosesoak commented Feb 15, 2017

Swift has a beautiful syntax for the case where you just want to assume a value is non-null, using a bang to 'unwrap' an unsafe value, like myObj!.

Like if you have a getMenuItem(key:string): ?Object method you can call,
const sports:Object = this.getMenuItem(MenuKeys.SPORTS)!

This lends itself to much shorter inline code like this.getMenuItem(MenuKeys.SPORTS)!.selectable = true.

The bang syntax indicates the circumvention of type-safety in specific cases where you are positive a value will exist so it's naturally self-documenting.

Personally I'd love a feature like that in Flow since currently I'm writing big null checks after getting values I am certain will not return null.

@vkurchatkin
Copy link
Contributor

I use a function like this:

function unwrap<T>(val: ?T): T {
  if (val == undefined) throw new Error();
  return val;
}

@calebmer
Copy link
Contributor

Closing since the initial issue has been resolved. You can cast through any 👍

The correct solution is to fix our libdefs. We’d be happy to accept PRs 😊

@aleclarson
Copy link

I agree with @mosesoak 100%. Why not make maybe-unwrapping more concise? 😕

MDev128 pushed a commit to MDev128/react-draggable that referenced this issue Aug 13, 2018
MDev128 added a commit to MDev128/react-draggable that referenced this issue Aug 13, 2018
ludarkhorse added a commit to ludarkhorse/ReactGrid that referenced this issue Feb 21, 2023
wdavis122 added a commit to wdavis122/react-draggable that referenced this issue Jun 5, 2024
Tarasiuk00000 added a commit to Tarasiuk00000/react-draggable that referenced this issue Jan 30, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants