Advanced
Code Generation
For additional compile-time and runtime safety including autocompletion, we can generate code from our already defined features for improved developer experience.
Why generate code?#
This is an optional step that we may wish to adopt in our workflow. If we do, it will help us avoid some common mistakes:
- any unintentional spelling mistakes in feature and variable keys
- worrying about the types of our variables
- worrying about passing attributes in wrong types in context
All of it done being code-driven, thus reducing overall cognitive load of multiple teams.
Supported languages#
Currently only TypeScript is supported.
Support for other languages is planned in future, as Featurevisor SDK becomes available in more languages.
Generate code#
From the root of our Featurevisor project directory, use the CLI for generating code in a specified directory:
$ npx featurevisor generate-code \ --language typescript \ --out-dir ./src \ --reactThe generated files can be found in ./src directory.
Some of the key generated files are:
context.ts: typedContextinterface for SDK evaluationattributes.ts: generated attribute types, such asCountryAttributeorAccountAttributeschemas.ts: generated reusable schema typesfeatures.ts: feature keys, variation values, feature variable keys, and feature variable value typesvariables.ts: global variable keys and value typesfunctions.ts: typedisEnabled,getVariation, and overloadedgetVariablefunctionsinstance.ts: SDK instance wiring throughsetInstancereact.ts: optional typed React hooks when--reactis usedindex.ts: exports the generated modules
Generated TypeScript uses FeatureVariableKey and FeatureVariableType for variables owned by features, and GlobalVariableKey and GlobalVariableType for independently defined variables. Regenerating code created by an older generator can therefore require import updates where the former VariableKey or VariableType names were used directly.
Optional flags:
--tag=<tag>: generate code for features and global variables with the given tag--target=<target>: generate code for features and global variables selected by the target--react: also generate typed React hooks inreact.ts
Both --tag and --target can be repeated. Every supplied tag and target forms one union across features and global variables. This is useful when one generated package serves several datafiles:
$ npx featurevisor generate-code \ --language typescript \ --out-dir ./src \ --tag=shared \ --target=web \ --target=mobileA target uses tag or tags to select both features and global variables. includeFeatures and excludeFeatures filter features. includeVariables and excludeVariables filter global variables. These selectors match datafile builds. Build-time context does not remove generated types because code generation is not tied to one environment or one specialized datafile result.
Publishing the generated code#
We are free to use the generated code in any way we want.
We can choose to either:
- copy/paste the code in our applications, or
- publish the generated code as a private npm package and use it in multiple applications, like as
@yourorg/featurespackage
The publishing part can be done in the same deployment process right after deploying our generated datafiles.
Consuming the generated code#
Assuming we published the generated code as a private npm package @yourorg/features, we can consume it in our applications as follows.
Initialize Featurevisor SDK as usual, and make our newly created package aware of the SDK instance:
import { createFeaturevisor } from '@featurevisor/sdk'import { setInstance } from '@yourorg/features'const f = createFeaturevisor({ // ...})setInstance(f)Afterwards, we can import a common set of functions which are already aware of which feature keys we are allowed to use including their variable keys.
Importing functions#
Similar to JavaScript SDK's methods isEnabled, getVariation, and getVariable, we can import these functions with the same names:
import { isEnabled, getVariation, getVariable } from '@yourorg/features'const featureIsEnabled = isEnabled('featureKey')const featureVariation = getVariation('featureKey')const featureVariable = getVariable('featureKey', 'variableKey')const sharedVariable = getVariable('supportEmail')We can optionally pass additional context as the last argument:
const context = { userId: '123',}const featureIsEnabled = isEnabled('featureKey', context)const featureVariation = getVariation('featureKey', context)const featureVariable = getVariable('featureKey', 'variableKey', context)const sharedVariable = getVariable('supportEmail', context)Everything here is typed as per our defined features.
If we pass a wrong feature key, or a variable key that does not belong to the same feature, we will get a TypeScript error.
Importing React hooks#
If we passed --react in CLI, we can import React hooks with the same names as the original package @featurevisor/react:
import { useFlag, useVariation, useVariable } from '@yourorg/features'const isEnabled = useFlag('featureKey')const variation = useVariation('featureKey')const variable = useVariable('featureKey', 'variableKey')const sharedVariable = useVariable('supportEmail')Passing any wrong feature key or variable key combination will result in a TypeScript error.
The generated functions and React hooks pass their schema derived result types through the generic APIs of @featurevisor/sdk and @featurevisor/react. This keeps hand written generic calls and generated calls consistent, while generated code also validates feature and variable keys for the selected project.
We can optionally pass additional context as the last argument:
const context = { userId: '123',}const isEnabled = useFlag('featureKey', context)const variation = useVariation('featureKey', context)const variable = useVariable('featureKey', 'variableKey', context)Suggestions for package publishing#
You are advised to publish the generated code as a private npm package, with support for ES Modules (ESM).
When published as ES Modules, it will enable tree-shaking in your applications, thus reducing the bundle size.

