In the code below typscript compiler shows error in update method, saying that 'any' is not assignable to type 'never'. I noticed that keyof type not working when the type contains boolean mixed with other types. How can I make it compile having mixed type values in the type?
type ConfigState = {
isAdminSet: boolean;
isDatabaseConnected: boolean;
adminName: string;
};
export class ConfigManager {
state: ConfigState = {
isAdminSet: false,
isDatabaseConnected: false,
adminName: "",
};
update(key: keyof ConfigState, value: ConfigState[keyof ConfigState]) {
this.state[key] = value;
}
}
But this compiles:
type ConfigState = {
isAdminSet: boolean;
isDatabaseConnected: boolean;
};
export class ConfigManager {
state: ConfigState = {
isAdminSet: false,
isDatabaseConnected: false,
};
update(key: keyof ConfigState, value: ConfigState[keyof ConfigState]) {
this.state[key] = value;
}
}
CodePudding user response:
TLDR: TypeScript doesn't know if your value
will fit into the chosen property of state
.
In your first example, all the properties are boolean
, so any
is inferred as a boolean
. But as soon as you add an other type (here, a string
), any
can't be inferred without restricting the key
. Hence, it is inferred as never
, and you can't assign any
to never
.
In this case, you must (I think) use a generic for this. Moreover, this will ensure type safety.
Take a look at this section of TS documentation: https://www.typescriptlang.org/docs/handbook/2/generics.html#using-type-parameters-in-generic-constraints
type ConfigState = {
isAdminSet: boolean;
isDatabaseConnected: boolean;
adminName: string;
};
export class ConfigManager {
state: ConfigState = {
isAdminSet: false,
isDatabaseConnected: false,
adminName: "",
};
update<Key extends keyof ConfigState>(key: Key, value: ConfigState[Key]) {
this.state[key] = value;
}
}