Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Io-ts interface for properties with unknown keys

I'm trying to create an io-ts interface of the following:

export interface myInterface {
  [key:string]?: string | undefined | null
}

I want to turn this into the io-ts equivalent. The end goal is to combine it with another existing io-ts interface:

export const MyOtherInterfaceV = t.interface({
  requiredProp1: ValidString// custom type, checks string is populated
  requiredProp2: ValidString
  // All other fields marked as required
})

export type MyOtherInterface = t.TypeOf<typeof MyOtherInterfaceV>;

The idea is I need a type to represent a payload which will have some fields we require and must be valid, and some that we don't know about and can be optional. We want to combine these for use later on in processing, eventually being stored in dynamodb.

like image 916
jbailie1991 Avatar asked Jul 28 '20 22:07

jbailie1991


2 Answers

I think the answer you're looking for is record:

const myInterfaceCodec = t.record(t.string, t.union([t.string, t.undefined, t.null]));
export type MyInterface = t.TypeOf<typeof myInterfaceCodec>;

=> type MyInterface = { [x: string]: string | null | undefined; }

Your use case:

const myInterfaceV = t.record(t.string, t.union([t.string, t.undefined, t.null]));
export type MyInterface = t.TypeOf<typeof myInterfaceV>;

const myOtherInterfaceV = t.intersection([
    t.type({
        requiredProp1: t.string,
        requiredProp2: t.string
    }),
    myInterfaceV
]);
export type MyOtherInterface = t.TypeOf<typeof myOtherInterfaceV>;

const a: MyOtherInterface = {
    requiredProp1: "string",
    requiredProp2: "string2"
};

const b: MyOtherInterface = {
    requiredProp1: "string",
    requiredProp2: "string2",
    optionalProp1: "hello",
    optionalProp2: "world"
};
like image 114
vmatyi Avatar answered Nov 15 '22 04:11

vmatyi


Probably the most close to myInterface in io-ts is t.UnknownRecord

export const MyOtherInterfaceV = t.interface({
  requiredProp1: t.string,
  requiredProp2: t.string
})

const MyOtherInterface = t.intersection([ t.UnknownRecord, MyOtherInterfaceV ]);
like image 38
Daniele Ricci Avatar answered Nov 15 '22 05:11

Daniele Ricci