Home > Back-end >  Infer the key type of the array object
Infer the key type of the array object

Time:07-19

I have the next example

type C = [
    {name: 'a'},
    {name: 'b'},
    {name: 'c'},
]

And I want to infer a new type SomeType based on the type C described above like this

const a: SomeType<C> = {
    a: () => {},
    b: () => {},
    c: () => {},
}

And so that there is a check of all keys. The following example must be invalid

const a: SomeType<C> = {
    a: () => {},
    b: () => {},
    // Error. "c" is not defined
}

I have tried to solve my problem like in the playground, but my solution doesn't check presence all keys

CodePudding user response:

Here's one approach:

type SomeType<T extends { [k: number]: { name: string } }> =
    Record<T[number]['name'], () => void>;

It accepts T constrained to a type with a numeric index signature (such as an array) whose elements have a name property of type string.

And it evaluates to a type whose keys are those string-assignable name properties (using T[number]['name'], a series of indexed access types), and whose value types are a function (I chose () => void but you might have a more specific type you care about). This uses the Record<K, V> utility type to represent an object type with keys of type K and values of types V.

Let's try it out:

const ports: SomeType<C> = { // error, missing b and c
    a: () => { },
}    

const ports2: SomeType<C> = {
    unknownkey: () => { }, // error, unknown key in object literal 
                           // (note, only errors for object literal)
}

const ports3: SomeType<C> = { // okay
    a: () => { },
    c: () => { },
    b: () => { },
}

Looks good!

Playground link to code

CodePudding user response:

You need a mapped type to map from the array type to your desire type:

type SomeType<T extends Array<{ name: string }>> = {
  [P in T[number]['name']]: () => void
}

Playground Link

  • Related