#Object with key as one type and all other types as object
18 messages · Page 1 of 1 (latest)
!:known*
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>;
}
Hmm that response isn’t very good
i mean, it's how ts works, what other response do you want
"Isn't very good" as in "you misunderstood my question, I'm not asking about mixing known and unknown keys" or something else?
The Compiles type doesn’t work though, you can’t do an intersection.
The unknown objects isn’t ideal.
The intersection would only work if key: string is type string | number so that type is already wrong in the answer, but ideally I would want with just string but it just doesn’t work that way.
Can you show me an assertion example?
The compile type does work though?
// No compile error
type Compiles = { [key: string]: number;}
& { specificKey: string };
I want to use it as type, if I assign it to my obj then it’ll complain
Yes, that's what's said in the snippet.
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).
Which leads up to the conclusion that if you can change your API, change it so you are not mixing known and unknown keys.
right, it's not the recommended solution. it's just an example of the recommended structure.
you can change the unknownKeys to some other key and restrict the Record type as needed.
Thank you! I will resolve this issue 🙂