Reputation: 288
Wassup guys, can someone help me with an typing error regarding interfaces? This issue drives me crazy, I am not sure how to avoid this error without using @ts-ignore.
This is my function:
function proceed() {
// @ts-ignore
let mockOptions: MockOptions = {};
Object.keys(models).forEach((modelKey) => {
const _modelKey = modelKey as keyof MockOptions;
const model = models[_modelKey];
// @ts-ignore
if (model.id.includes("not")) {
mockOptions[_modelKey] = false;
} else {
mockOptions[_modelKey] = true;
}
});
emit("proceed", mockOptions);
}
This is my interface:
export interface MockOptions {
hasHotelComment: boolean;
isInStornofrist: boolean;
withDifferentBillingAddress: boolean;
paymentOption: string;
}
What do I want to achieve? I do render RadioButtons that I receive from my Mock, to change data properties for show cases. Normally they are booleans, now I want to add string so I can set values from the selected Radio. However, I receive this error, because of the added 'paymentOption: string', when I switch to 'boolean', this error disappears:
TS2322: Type 'boolean' is not assignable to type 'never'.
const _modelKey: keyof MockOptions
Upvotes: 1
Views: 373
Reputation: 15776
You can define a new type of all object keys that hold boolean values using a mapped type:
type BooleanKeys<T> = keyof {[K in keyof T as T[K] extends boolean ? K : never]: any}
const _modelKey = modelKey as BooleanKeys<MockOptions>; // "hasHotelComment" | "isInStornofrist" | "withDifferentBillingAddress"
Since you were asking, let's break it down by parts:
type BooleanKeys<T> = keyof // take only the keys
{[ // from a mapped type
K in keyof T // where keys are those of T
as // but cast them to
T[K] extends boolean ? K : never // themself if their value is boolean, otherwise nothing (remove them)
]: any // we throw away the values, so anything is fine
}
The heavy lifting is done by the as
, the documentation has more on that.
Upvotes: 1