Is there a way to enforce dynamic keys in typescript?
I am trying to achieve a type that enforces objects to have a create and an update keys but those keys should be prefixed with a domain text:
const productRepoA: Repo = { } // Should fail because create and update keys are missing
const productRepoB: Repo = { productCreate: () => null } // Should fail because update key is missing
const productRepoC: Repo = { productUpdate: () => null } // Should fail because update key is missing
const productRepoD: Repo = { productCreate: () => null, productUpdate: () => null } // Should work because both keys are provided
const orderRepoA: Repo = { } // Should fail because create and update keys are missing
const orderRepoB: Repo = { orderCreate: () => null } // Should fail because update key is missing
const orderRepoC: Repo = { orderUpdate: () => null } // Should fail because update key is missing
const orderRepoD: Repo = { orderCreate: () => null, orderUpdate: () => null } // Should work because both methods are provided
I thought something like this should work:
type Repo = {
[key: `${string}Create`]: () => null
} & {
[key: `${string}Update`]: () => null
}
But sadly, that allows missing keys like option A, B and C in my examples
this will solve the problem but you must explicitly specify the key:
type Repo<T extends string> = {
[a in `${T}Update` | `${T}Create`]: () => null
// [b : `${T}Update`]: () => null
}
const productRepoA: Repo<"product"> = { } // Should fail because create and update keys are missing
const productRepoB: Repo<"product"> = { productCreate: () => null } // Should fail because update key is missing
const productRepoC: Repo<"product"> = { productUpdate: () => null } // Should fail because update key is missing
const productRepoD: Repo<"product"> = { productCreate: () => null, productUpdate: () => null } // Should work because both keys are provided
const orderRepoA: Repo<"order"> = { } // Should fail because create and update keys are missing
const orderRepoB: Repo<"order"> = { orderCreate: () => null } // Should fail because update key is missing
const orderRepoC: Repo<"order"> = { orderUpdate: () => null } // Should fail because update key is missing
const orderRepoD: Repo<"order"> = { orderCreate: () => null, orderUpdate: () => null } // Should work because both methods are provided