Not sure if the title is explicit (it was not easyto describe this issue in one sentence) but here is some code to illustrate the issue (more details about the issue after the code block):
type AttributeDefinition = {
name:string
type: 'string' | 'number',
}
type EntityDefinition = {
attributes: Readonly<AttributeDefinition[]>
}
export type Entity<ET extends EntityDefinition> = {
[K in ET['attributes'][number] as K['name']]:
K['type'] extends 'string' ? string :
K['type'] extends 'number' ? number :
never
}
const def1 = {
attributes: [
{name:'foo', type: 'string'},
{name:'baz', type: 'number'},
] as const
}
const def2: EntityDefinition = {
attributes: [
{name:'foo', type: 'string'},
{name:'baz', type: 'number'},
] as const
}
const entity1: Entity<typeof def1> = {
foo: 'bar',
baz: 42
}
const entity2: Entity<typeof def2> = {
foo: 'bar',
baz: 42
}
So my issue is that typescript throw an error on entity2 when I want to assign 'bar' to foo (and 42 to baz). The issue is TS2322: Type 'string' is not assignable to type 'never'.
However, this issue does not occurs with entity1.
The origin of this issue seems to be related to the declaration of def2 for which I annotate the EntityDefinition type. I am doing this so I can have typing hint from my IDE helping me to properly declare the def2 object.
But the def1 object, even if not type annotated, is later properly handled when creating the entity1, whereas def2 (that I would expect to be typed the right way) fails when it is used to create the entity2.
I am not really sure to understand why it does fail in such a way, and how can I annotate a object as I do for def2 and also use such an object later as I do for entity1.
Thanks!