Skip to content

Instantly share code, notes, and snippets.

@Ezku
Last active June 5, 2018 11:44
Show Gist options
  • Save Ezku/3db645a8b9f9f9835a2b102577f0da5b to your computer and use it in GitHub Desktop.
Save Ezku/3db645a8b9f9f9835a2b102577f0da5b to your computer and use it in GitHub Desktop.
Opaque type projection does not maintain exactness
/* @flow */
import {
type Tagged, // eslint-disable-line import/named
tagged
} from './tagged';
// I can create tagged values...
const taggedString: Tagged<string> = tagged('asdf');
// ...and those values can be used as the type that was provided as the argument to `Tagged`:
const untaggedString: string = taggedString;
// This works for object types too:
const taggedObject: Tagged<{ works: boolean }> = tagged({ works: true });
const untaggedObject: { works: boolean } = taggedObject;
// But fails to work for object types flagged exact:
const taggedExactObject: Tagged<{| works: boolean |}> = tagged({
works: false
});
// $FlowFixMe
const untaggedExactObject: {| works: boolean |} = taggedExactObject;
// Cannot assign taggedExactObject to untaggedExactObject because inexact Tagged [1] is incompatible with
// exact object type [2].
//
// [1] 14│ const taggedExactObject: Tagged<{| works: boolean |}> = tagged({
// 15│ works: false
// 16│ });
// [2] 17│ const untaggedExactObject: {| works: boolean |} = taggedExactObject;
// 18│
/* @flow */
export opaque type Tagged<A>: A = A;
export const tagged = <A>(value: A): Tagged<A> => value;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment