Home > OS >  How can I define an object type with one value if the key is in an array and another value if not
How can I define an object type with one value if the key is in an array and another value if not

Time:07-07

I have a function something like:

function allFinished(pendingProps: string[], allProps: Record<string, unknown>): boolean {
    return pendingProps.every((pendingProp) => allProps[pendingProp].isFinished)
}

For typescript to be happy with me, it needs to know that each allProps key which is an element of pendingProps will have a value that includes isFinished. But I also need it to be okay with keys which are not in pendingProps having a different value type.

This would be fairly simple if pendingProps was defined ahead of time and could be marked as const, but I can't figure out how to do this with with an arbitrary string array.

CodePudding user response:

We should make allFinished generic for this to be properly typed.

function allFinished<
  T extends Record<K, { isFinished: boolean }> & Record<string, unknown>, 
  K extends string
>(pendingProps: K[], allProps: T): boolean {
    return pendingProps.every((pendingProp) => allProps[pendingProp].isFinished)
}

The essentially expresses the constraints you mentioned in your question. All pendingProps will be stored in K while the allProps object is stored in T. T is constrained so that every property where the key is part of K must have a property isFinished. But every other string property will have an unknown type.

Let's see if this works:

allFinished(["a", "b", "c"], {
    a: { isFinished: true },
    b: { isFinished: false },
    c: {},  // Error: Property 'isFinished' is missing in type '{}' but required in type '{ isFinished: boolean; }'
    d: {}
})

Playground

  • Related