Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript: Reference type of property by other property of same object

Tags:

typescript

See the following code:

interface X {
    a: string;
    b: number;
    c: boolean;
}

type A = {
    prop: keyof X;
    value: X[keyof X];
}

const a: A = { prop: 'a', value: 'a' }; // ok
const b: A = { prop: 'a', value: 1 }; // not ok, value should be string, because X['a'] is string
const c: A = { prop: 'b', value: 1 }; // ok
const d: A = { prop: 'c', value: 1 }; // not ok, value should be boolean, because X['c'] is boolean

Here I want the type of the .value property to be string, if prop is "a", number for "b" and boolean for "c", but instead it is string|number|boolean for all cases, because keyof X can refer to different keys for each use for type A. How can I make it refer to the same property twice, without having it explicitly input it into a generic argument of A?

I feel like I should be using infer her, but I'm not sure how, and also I might be on the wrong track there.

like image 974
Bart van den Burg Avatar asked Oct 30 '25 08:10

Bart van den Burg


1 Answers

You want A to be a union of {prop: K; value: X[K]} for each K in keyof X, like this:

type A = {
    prop: "a";
    value: string;
} | {
    prop: "b";
    value: number;
} | {
    prop: "c";
    value: boolean;
};

In each element of that union, there is a correlation between the prop type and the value type, which prohibits you from assigning prop and value types from different members of X:

const a: A = { prop: 'a', value: 'a' }; // ok
const b: A = { prop: 'a', value: 1 }; // error
const c: A = { prop: 'b', value: 1 }; // ok
const d: A = { prop: 'c', value: 1 }; // error

You can also make the compiler calculate this for you programmatically in a few ways, such as building a mapped type that you immediately index into:

type A = { [K in keyof X]-?: {
    prop: K;
    value: X[K];
} }[keyof X];

It can be verified via IntelliSense that the above definitions of A are equivalent, but now A will update automatically if you modify X.

Playground link to code

like image 145
jcalz Avatar answered Nov 02 '25 01:11

jcalz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!