Pesquisa de site

typescript - Tipo 'any' não é atribuível ao tipo 'never' ao tentar definir uma propriedade de objeto com uma variável que é keyof ObjectType


No código abaixo, o compilador TypeScript mostra erro no método update, dizendo que 'any' não é atribuível ao tipo 'never'. Percebi que keyof tipo não funciona quando o tipo contém booleano misturado com outros tipos. Como posso fazer compilar tendo valores de tipos mistos no tipo?

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;
  }
}

Mas isso compila:

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;
  }
}

Resposta #1

TLDR: O TypeScript não sabe se o seu value caberá na propriedade escolhida de state.

No seu primeiro exemplo, todas as propriedades são boolean, então any é inferido como um boolean. Mas assim que você adiciona outro tipo (aqui, um string), any não pode ser inferido sem restringir a key. Portanto, ele é inferido como never, e você não pode atribuir any a never.

Neste caso, você deve (acho) usar um genérico para isso. Além disso, isso garantirá a segurança de tipo.

Dê uma olhada nesta seção da documentação do TS: 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;
  }
}

Artigos relacionados