Skip to content

Instantly share code, notes, and snippets.

@stephencweiss
Created February 10, 2023 20:06
Show Gist options
  • Save stephencweiss/e10f5a072e06b7e2703c8d228bfaf2fb to your computer and use it in GitHub Desktop.
Save stephencweiss/e10f5a072e06b7e2703c8d228bfaf2fb to your computer and use it in GitHub Desktop.
io-ts Partial records
import { map } from 'fp-ts/Record';
import * as t from 'io-ts';
export const StandardCodec = t.type({ fields: t.string });
export type Standard = t.TypeOf<typeof StandardCodec>;
// export const OriginalCodec = t.type({ original: t.string });
// export type Original = t.TypeOf<typeof OriginalCodec>;
export const partialRecord = <K extends string, T extends t.Any>(
k: t.KeyofType<Record<string, unknown>>,
type: T,
): t.PartialC<Record<K, T>> => t.partial(map(() => type)(k.keys));
const SupportedEnvCodec = t.keyof({ prod: null, qa: null, dev: null });
type SupportedEnv = t.TypeOf<typeof SupportedEnvCodec>;
type ProdEnv = Extract<SupportedEnv, 'prod'>;
const ProdEnvCodec: t.Type<ProdEnv> = t.literal('prod');
type OtherEnv = Exclude<SupportedEnv, 'prod'>;
const OtherEnvCodec: t.KeyofType<Record<OtherEnv, unknown>> = t.keyof({ qa: null, dev: null });
export const StrictExtendedCodec = t.intersection([
t.record(ProdEnvCodec, StandardCodec),
t.record(OtherEnvCodec, StandardCodec)]);
export type StrictExtended = t.TypeOf<typeof StrictExtendedCodec>;
const LooseExtendedCodec = partialRecord<OtherEnv, typeof StandardCodec>(
OtherEnvCodec, StandardCodec,
);
export const ExtendedCodec = t.intersection([
t.record(ProdEnvCodec, StandardCodec),
LooseExtendedCodec]);
export type Extended = t.TypeOf<typeof ExtendedCodec>;
// Errors
const strict: StrictExtended = {
prod: {fields: ''},
dev: {fields: ''},
};
// Compiles
const loose: Extended = {
prod: {
fields: '',
},
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment