Orelus
Orelus

Reputation: 1023

Typing nested array of objects

How can I define foo so that i don't have to specify as Constraint for each of the array items ?

type Constraint = {
    constraint: 'required' | 'equal'
}


function bar<K extends string>(d: Record<K, Constraint[]>) {
    return Object.keys(d).reduce((a, b) => (a[b] = '', a),
                                 {} as { [key: string]: string }) as Record<K, string>
}

const foo = { apple: [ { constraint: 'required' } ] }
// Error  Type 'string' is not assignable to type '"required" | "equal"'.
const baz = bar(foo)


// Works fine
const foo2 = { apple: [  { constraint: 'required' } as Constraint ] }
const baz2 = bar(foo2)

Upvotes: 1

Views: 97

Answers (1)

leonardfactory
leonardfactory

Reputation: 3501

When you type a string, TS recognizes it as a plain string, not like the 'required' literal. You can:

  1. Use the object literal directly in the function call:
const baz = bar({ apple: [ { constraint: 'required' } ] })

This way inference is preserved

  1. Declare the string as const, i.e.:
const foo = { apple: [ { constraint: 'required' as const } ] }

This lets know TS that you don't mean a generic string but the exact literal you typed. In older TS version as const is not present buy you could still use 'required' as 'required'

Upvotes: 3

Related Questions