Pergunta

A especificação TypeScript afirma em §4.15.6 sobre o && operador:

O operador && permite que os operandos sejam de qualquer tipo e produz um resultado do mesmo tipo que o segundo operando.

Em Javascript, o && operador retorna o primeiro operando se for falso, caso contrário retorna o segundo operando (consulte ECMA-262 §11.11).

Isso significa que se o operando esquerdo for falso, && retornará um valor que corresponde ao tipo do operando esquerdo.Por exemplo,

typeof ( false && {}      ) === "boolean" // true
typeof ( ''    && 1       ) === "string"  // true
typeof ( null  && "hello" ) === "object"  // true
typeof ( NaN   && true    ) === "number"  // true

O texto datilografado, de acordo com a regra citada acima, seria incorretamente prever os tipos das expressões acima como sendo Object, Number, String e Boolean, respectivamente.

Estou esquecendo de algo?Existe uma boa razão para fazer o tipo de && expressão corresponde ao tipo do segundo operando?O tipo de resultado não deveria se comportar como o || operador e retornar o melhor tipo comum dos dois operandos, e Any se não houver melhor tipo comum?

Foi útil?

Solução

Resumindo, não há solução aqui que agrade a todos.

Considere este idioma comum:

var customer = GetCustomer(...); // of type 'Customer'
var address = customer && customer.address;
if(address) {
    printAddressLabel(address); // Signature: (Address) => void
} else {
    // Couldn't find the customer or the customer has no address on file
}

Seria muito chato desistir e decidir que 'endereço' é 'qualquer' porque não existe um tipo comum entre Cliente e Endereço.

Na maioria dos casos em que o operador && é usado, os tipos match, ou && está sendo usado de maneira aglutinadora de valores, como acima.Em ambos os casos, retornar o tipo do operando correto fornece ao usuário o tipo esperado.

Embora a segurança de tipo esteja tecnicamente falhando neste ponto, ela não está fazendo isso de uma forma que possa resultar em um erro.Ou você testará a veracidade do valor resultante (nesse caso, o tipo é mais ou menos irrelevante) ou usará o presumível operando correto para alguma operação (o exemplo acima faz as duas coisas).

Se olharmos para os exemplos que você listou e fingirmos que o operando esquerdo é indeterminadamente verdadeiro ou falso e então tentarmos escrever um código sensato que operaria no valor de retorno, ficará muito mais claro - simplesmente não há muito que você possa fazer com 'false && {}' que ainda não está entrando em uma posição de argumento 'qualquer' ou teste de veracidade.


Termo aditivo

Como algumas pessoas não ficaram convencidas com o que foi dito acima, aqui está uma explicação diferente.

Vamos fingir por um momento que o sistema de tipos TypeScript adicionou três novos tipos: Truthy<T>, Falsy<T>, e Maybe<T>, representando possíveis valores verdadeiros/falso do tipo T.As regras para esses tipos são as seguintes:

  1. Truthy<T> se comporta exatamente como T
  2. Você não pode acessar nenhuma propriedade de Falsy<T>
  3. Uma expressão do tipo Maybe<T>, quando usado como a condição em um if bloco, torna-se um Truthy<T> no corpo desse mesmo if bloco e um Falsy<T> no else bloquear

Isso permitiria que você fizesse coisas assim:

function fn(x: Maybe<Customer>) {
   if(x) {
      console.log(x.address); // OK
   } else {
      console.log(x.phone); // Error: x is definitely falsy
   }
   console.log(x.name); // Warning: x might be falsy!
}

Muito bom até agora.Agora podemos descobrir quais são as regras de tipo para o operador &&.

  • Truthy<T> && x deveria ser um erro - se o lado esquerdo for verdadeiro, você deveria ter escrito x
  • Falsy<T> && x deveria ser um erro - se o lado esquerdo for falso, x é um código inacessível
  • Maybe<T> && x deveria produzir...o que?

Sabemos o resultado de Maybe<T> && x será um valor falso do tipo T, ou x.Não pode produzir Truthy<T> (a menos que T == o tipo de x nesse caso, toda essa discussão é discutível).Vamos chamar esse novo tipo Falsy<T> XOR Maybe<U>.

Quais devem ser as regras de Falsy<T> XOR Maybe<U> ser?

  • Claramente, você não pode usar propriedades de T nele.Se o valor for do tipo T, é falso e não é seguro para uso.
  • Você deve ser capaz de usá-lo como um Maybe<U>, desde Falsy<T> e Falsy<U> têm os mesmos comportamentos
  • Você não deveria poder usar propriedades de U, porque o valor ainda pode ser falso.
  • Se você usá-lo em um if teste, então ele deve se tornar um Truthy<U> no bloco daquele if declaração

Em outras palavras, Falsy<T> XOR Maybe<U> é Maybe<U>.Segue todas as mesmas regras.Você não precisa complicar o sistema de tipos aqui adicionando este estranho XOR tipo, porque já existe um tipo que atende a todas as especificações que você precisa.

É como dar uma caixa a alguém e dizer “Esta é uma caixa vazia de lixo ou uma caixa cheia de recicláveis”.Você pode esvaziar com segurança o conteúdo da caixa na lixeira.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top