-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
Cast to opaque type #6957
Comments
You can reproduce this in Flow Try using I think that you may be misunderstanding the purpose of opaque types. Consider the following example. We can have a module // @flow
export opaque type NonNegative: number = number;
export function asNonNegative(x: number): NonNegative {
if (x < 0) throw new Error("negative: " + x);
return x;
}
export function add(x: NonNegative, y: NonNegative): NonNegative {
return x + y;
} From another module, it is not valid to write import { asNonNegative, add, type NonNegative } from "./nonneg";
const one: NonNegative = asNonNegative(1);
const two: NonNegative = add(one, one); Because const works: number = one - two; because const fails: NonNegative = one - two; // fails to typecheck (good!) If we could just write |
Many thanks for such a descriptive answer. I was looking for a way to define a millisecond timestamp type in my application to avoid providing other timestamp types (e.g. microseconds) for functions that expect exactly a millisecond timestamp. Is it a valid use case for opaque types? If not how, is there any other construction to achieve that. Here is an example: Flow Try - opaque types |
Opaque types are one good solution here, yes. I suggest defining the following simple module: // @flow
export opaque type MillisecondsTimestamp = number;
export function fromMilliseconds(milliseconds: number): MillisecondsTimestamp {
return milliseconds;
}
export function toMilliseconds(timestamp: MillisecondsTimestamp): number {
return timestamp;
} Then, you can write client code like the following: // @flow
import {
type MillisecondsTimestamp,
fromMilliseconds,
toMilliseconds,
} from "./millisecondsTimestamp";
function now(): MillisecondsTimestamp {
return fromMilliseconds(Date.now());
}
function isCloseToNow(ts: MillisecondsTimestamp) {
return toMilliseconds(ts) > toMilliseconds(now()) - 1000 * 60;
} (Flow Try link to example here.) The key thing to note is that in the client code, all conversions are Does this make sense? |
Depending on your constraints, another reasonable solution would be to type TimeUnit = "SECONDS" | "MILLISECONDS" | "MICROSECONDS";
type Duration = {|+unit: TimeUnit, +scalar: number|}; If you control the implementations of all the functions that you’re |
This is exactly the answer I was looking for. Many thanks for that. |
Great; glad to have helped. |
Unfortunately, opaque types seem to be not supported by flow-runtime gajus/flow-runtime#209 which is used by babel-plugin-flow-runtime. |
It sounds like (Opaque types are a pretty critical feature. It’s not heartening that |
I have recently took over development of flow-runtime project. Will prioritise fixing this. If there is any interest to contribute a PR, will happily streamline it. |
Hi, I would like to use custom opaque type build on top of number type, but working with opaque types seems to be problematic.
Unfortunately, it is impossible to reproduce that on http://flow.org/try because it requires more than one file (one which exports opaque type and other which imports it).
Here is my problem:
Exported types e.g. index.js.flow
Imported types e.g. index.js
Is there any casting method which I'm not aware of?
Message in error cases is similar to this:
The text was updated successfully, but these errors were encountered: