Can I constrain the value type of a map entry depending on the item's key?
type Thing<T extends string = any> = {
type: T
}
type ThingMap<T extends Thing> = {
[K in T["type"]]: T
}
interface A {
type: "A",
foo: boolean,
}
interface B {
type: "B",
}
// This compiles.
const map: ThingMap<A | B> = {
A: { type: "A", foo: true },
B: { type: "B" },
}
// But this also compiles, when it should not.
const map: ThingMap<A | B> = {
A: { type: "A", foo: true },
B: { type: "A", foo: true },
}
You want to ensure that for a specific K the type of the key is not the whole union (ie T) but rather just the member of the union with the type K. You can use Extract to get the member of the union that has the property type of type K:
type Thing<T extends string = any> = {
type: T
}
type ThingMap<T extends Thing> = {
[K in T["type"]]: Extract<T, { type : K }> // Extract the union member that has { type: K }
}
interface A {
type: "A",
foo: boolean,
}
interface B {
type: "B",
}
// This compiles.
const map: ThingMap<A | B> = {
A: { type: "A", foo: true },
B: { type: "B" },
}
// Err now
const map2: ThingMap<A | B> = {
A: { type: "A", foo: true },
B: { type: "A", foo: true },
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With