TypedConfig

TypedConfig is a simple solution for managing multi-environment application settings whilst maintaining type safety.

Currently, only Rails is supported out of the box.

TypedConfig is meant to run in projects using Sorbet, although it can run in projects not using it and still gain from the easy-to-configure settings.

This project has been inspired by Config and it's meant to be an easy drop-in replacement with type-safety.

 Installing

Add the gem to your Gemfile:

gem 'typed-config'

Run the install rake task to initialize the config schema and settings files:

rails g typed_config:install

This will generate the schema file config/config.rb where the schema of the settings should be defined, and the settings file:

config/settings.yml
config/settings.local.yml
config/settings/development.yml
config/settings/production.yml
config/settings/test.yml

It will also update the existing .gitignore to local settings files.

Defining the Settings Properties

First, the schema of the Settings object must be defined in the config/config.rb file, for example:

TypedConfig::Schema.configure do |s|
  s.const :env, String
  s.const :app do
    s.const :domain, T.nilable(String)
    s.const :port, T.nilable(Integer)
  end
  s.const :support do
    s.const :email, String
  end
end

Now in the code, you can access any properties as a T::Struct. All properties will be available across the application in a Settings object:

Settings.env
Settting.support.email

# Example:
config.action_mailer.asset_host = "https://#{Settings.app.domain}"

Changing the Settings

The settings are defined in YAML (with ERB support). Once the schema is defined, update one of the settings file to load the data:

env: <%= ENV['RACK_ENV'] %>
app:
  domain: <%= ENV['APP_DOMAIN'] %>
  port: <%= ENV.fetch('APP_PORT', 3000) %>
support:
  email: '[email protected]

When loaded, typed-config will try to automatically coerce the values to match the ones specified in the schema.

You may define default (or different) settings for each environment by changing the config/settings/#{env}.yml. For instance, to have different defaults in the test environment, add the settings to config/settings/test.yml.

In order from top to bottom - the settings in the lower files overwrite the ones higher - these are the files loaded:

config/settings.yml
config/settings/#{environment}.yml

config/settings.local.yml
config/settings/#{environment}.local.yml

Type Safety

To make use of the type-safety feature, you must re-generate the RBI files when the schema is changed using a rake command:

bundle exec rake typed-config:rbi

Now you can run sorbet to check the types of the settings properties:

T.reveal_type(Settings.app.domain) # Revealed type: T.nilable(String)

sig { params(server_write_key: String).void }
def configure_segment(server_write_key); end


configure_segment(server_write_key: Settings.segment.server_write_key)
# Expected String but found T.nilable(String) for argument server_write_key