JSMonk / hegel

An advanced static type checker
https://hegel.js.org
MIT License
2.09k stars 59 forks source link

type assertions #190

Open thecotne opened 4 years ago

thecotne commented 4 years ago

i am doing something like this in flow

type NotificationAction =
  | 'ScheduleCreated'
  | 'ScheduleStarttimeUpdated'
  | 'ScheduleCancelled'
  | 'DiagnosisPublished'
  | 'PatientCaseFinished'
  | 'MydocGreeted'

type NotificationBase = {|
  +id: string,
  +created_at: string
|}

type Notification = {|
  ...NotificationBase,
  +action: NotificationAction,
  +entity_id: string,
|}

export type NotificationExpanded =
  | {|
      ...NotificationBase,
      +action: 'ScheduleCreated' | 'ScheduleStarttimeUpdated' | 'ScheduleCancelled',
      +schedule: {...}
    |}
  | {|
      ...NotificationBase,
      +action: 'PatientCaseFinished',
      +patientCase: {...}
    |}
  | {|
      ...NotificationBase,
      +action: 'MydocGreeted' | 'DiagnosisPublished'
    |}

// -- EXHAUSTIVE CHECKING --

declare var _asrt01: $PropertyType<NotificationExpanded, 'action'>
/*:: (_asrt01: NotificationAction) */

declare var _asrt02: NotificationAction
/*:: (_asrt02: $PropertyType<NotificationExpanded, 'action'> ) */

// -- END OF EXHAUSTIVE CHECKING --

try

i am checking that object union has all actions from NotificationAction and nothing extra

in flow this is very hacky but in hegel i think it's impossible to achieve same result because i can't declare var and i can't use type casting (type casting can be replaced with variable declaration but then i have reference of undefined variable in code)

thecotne commented 4 years ago

it would be cool to have first class support for this kind of things

for example with syntax like this

// @hegel-assert $PropertyType<{ type: 'cotne' }, 'type'> @is 'cotne'
// @hegel-assert $PropertyType<{ type: 'cotne' }, 'type'> @is-not 'name'
// @hegel-assert $PropertyType<{ type: 'cotne' }, 'type'> @is-sub-type-of string
// @hegel-assert $PropertyType<{ type: 'cotne' }, 'type'> @is-sub-type-of 'cotne' | 'name'

this will allow custom exhaustive checking (and maybe even more)

JSMonk commented 4 years ago

Good point. I need to think about it, especially about the syntax. Thank you for your contribution ^_^.