#Angle bracket type argument with index signature

1 messages · Page 1 of 1 (latest)

slim onyx
#

I want to have an object where the key 0 has the value of type A, but every other number has type B. So far I've tried this:

type o = {
    readonly [key: number]: B;
    readonly 0: A;
};

But this doesn't work because A isn't assignable to B and B isn't assignable to A. I've also tried this:

type o = {
    readonly <keyType extends number>[key: keyType]: keyType extends 0 ? A : B;
};

But this also doesn't work. Does anyone have any idea on how to achieve what I want?

lean dagger
#
type YourType = { readonly 0: number } | Readonly<Record<number, string>>;

const obj: YourType = {
    0: 123,
    42: 'foo',
};```
#

You can replace number and string with A and B.

slim onyx
#

Is it also to have the combination of the key 0 and other numbers here? Because it seems like with | like the type can be either only 0 or other number

lean dagger
#

Could you rephrase your question?

slim onyx
#

I want it to be able to have both 0 and other numbers

lean dagger
#

I gave you a working example, though.

slim onyx
#

But why does it work then

lean dagger
#

If it didn't work, I wouldn't have posted it as an answer. 😅

slim onyx
#

I think it has something to do with the Record, because if I try with a normal object it doesn't work.

blazing dome
#

It seems like the downside of the union is that if you access obj[0] then it's string | number, not number.

slim onyx
#

Yes, I was about to say that

#

I want obj[0] to be number and obj[42] to be string

blazing dome
#

!*:known-and-unknown-keys

scarlet radishBOT
#
Retsam19#2505
`!retsam19:known-and-unknown-keys`:

TS doesn't work well with objects that mix "known keys" of one type onto an object with unknown keys (i.e. an index signature) for a different type.

type DoesNotCompile = {
    [key: string]: number; // all unknown keys are numbers
    specificKey: string; // but this key is a string
}

You can 'fake' it with intersections:

type Compiles = { [key: string]: number;}
  & { specificKey: string };

but this type is essentially read-only. You can read from it as you'd expect, but you can't assign anything to this type (without an assertion).

If your API isn't set in stone, it's recommended to put the unknown keys in their own object:

type Idiomatic ={
   specificKey: string;
   unknownKeys: Record<string, number>;
}
lean dagger
slim onyx
#

I've tried the intersection, but it doesn't work. Why doesn't this work, and when can I use intersections like this?

blazing dome
#

Like the snippet says:

but this type is essentially read-only. You can read from it as you'd expect, but you can't assign anything to this type (without an assertion).

#

So you'd have to do const obj = { 0: 1, 1: 'hello' } as a, but since that's a type-assertion that could be masking other errors.