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!
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
}