Reputation: 4549
Having object A:
interface A {
boolProp: boolean,
stringProp: string,
numberProp: number,
...other props/methods...
}
Then I want to have objects, which holds one of the A properties and defines default value for it, other properties are irrelevant to this issue.
interface B {
prop: keyof A,
default: typeof keyof A,
...other props/methods...
}
I want to get TS error when I try to set default value of different type
const b: B = {
prop: 'stringProp',
default: true, // expecting to get TS error as true cannot be assigned to string
};
Thank you in advance for any help 🙏
Upvotes: 1
Views: 1060
Reputation: 2474
Another approach is to use a generic. It won't create a union type:
interface B<T extends keyof A> {
prop: T,
default: A[T]
// ...other props/methods...
}
const b: B<'stringProp'> = {
prop: 'stringProp',
default: true, // error
};
Of course the repetition of 'stringProp' is annoying. You may use a function or a class constructor instead and check the arguments passed to it, for example:
const createB = <T extends keyof A>(prop: T, defaultVal: A[T]) => ({ prop, default: defaultVal });
const b = createB('stringProp', true);
// error ----
Upvotes: 1
Reputation: 23925
You essentially want a union type which holds all valid prop
/default
combinations. This can be programmatically generated with a mapped type which maps over the keys of A
and is indexed with keyof A
.
type B = {
[K in keyof A]: {
prop: K
default: A[K]
}
}[keyof A] & {
/* ... put all the other props of B here */
}
Upvotes: 1