Skip to content

Instantly share code, notes, and snippets.

@robyurkowski
Last active October 24, 2023 23:24
Show Gist options
  • Save robyurkowski/7b91a93353ab95f5d75065d1382a5e07 to your computer and use it in GitHub Desktop.
Save robyurkowski/7b91a93353ab95f5d75065d1382a5e07 to your computer and use it in GitHub Desktop.
require "dry-types"
module DryTS
# We use this method to mark a type for inclusion in our generated TS types.
def ts_export(_assigned_type)
extract_constants!
# ... Other stuff for exporting TS
end
def extract_constants!
@__dry_ts_constants ||= {}
# constants(false) returns a list of constants for the module that aren't inherited.
# We wound up with a solution that was marginally more complex (using `constants(true)`
# and removing a list of types inherited from `include Dry.Types()`, which lets us
# mix in un-marked up type files and have their types be included, too)...
#
# ... but this is a lot simpler to show the proof of concept.
constants(false).each do |c|
# We don't want to accidentally include a non-Type object.
next unless (const = const_get(c)).class.ancestors.include?(Dry::Types::Type)
@__dry_ts_constants[c] = const.meta(name: c)
remove_const(c)
end
end
def const_missing(const)
@__dry_ts_constants[const]
end
def finalize_ts_exports!
# Do this one last time because there's no guarantee we ended on a ts_export.
extract_constants!
@__dry_ts_constants.each do |const_name, const|
const_set(const_name, const)
end
end
end
module Types
extend DryTS
include Dry.Types()
ts_export UUID = Types::String
# Even without exporting this explicitly, it's annotated in the AST for the next type:
MyString = Types::String
ts_export WeirdMap = Types::Hash.map(MyString, UUID)
finalize_ts_exports!
end
# >> Types::WeirdMap.to_ast
# =>
# [:map,
# [[:constrained, [[:nominal, [String, {:name=>:MyString}]], [:predicate, [:type?, [[:type, String], [:input, Undefined]]]]]],
# [:constrained, [[:nominal, [String, {:name=>:UUID}]], [:predicate, [:type?, [[:type, String], [:input, Undefined]]]]]],
# {:name=>:WeirdMap}]]
# >>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment