Validate property based on another property keys

Advertisements

I would like to improve the type-checking of the following object:

interface Config {
    fields: Record<string, unknown>;
    table: { id: string }[];
}

const config: Config = {
    fields: {
        id: {}
    },
    table: [
        { id: 'id' },
        { id: 'name' },
    ]
};

The part I’m struggling with is that I want to type-check that the table object id should match a key in fields. If table > id is not present in fields keys, then it should error. So:

  • { id: 'id' } is OK, since id key exists in fields
  • { id: 'name' } should error, name key doesn’t exist in fields

Is this possible? Plan B is to do this check at runtime.

>Solution :

It is not possible (yet) to create a standalone type which can do validation like that. But generic types are powerful enough to achieve this. Generic types for validation are best used in combination with a function.

function useConfig<F>(config: { fields: F, table: { id: keyof F }[]}) {}

In this function we have the generic type F which holds information about the object we pass with the fields property. We can then use keyof F inside table.

Some tests to validate the result:

useConfig({
    fields: {
        id: {}
    },
    table: [
        { id: 'id' }
    ]
})
// works

useConfig({
    fields: {
        id: {}
    },
    table: [
        { id: 'id' },
        { id: 'name' }
    ]
})
// error

useConfig({
    fields: {
        id: {},
        name: {}
    },
    table: [
        { id: 'id' },
        { id: 'name' }
    ]
})
// works

Playground

Leave a ReplyCancel reply