Eu tenho a seguinte lógica:
interface ResultBase {
readonly success: boolean
}
type Result<Payload = undefined> = ResultBase & (Payload extends undefined ? {
readonly payload?: unknown
} : {
readonly payload: Payload
})
function getResult<Payload = undefined>(payload: Payload): Result<Payload> {
return {
// ^^^^^^
success: true,
payload,
}
}
Tente .
A instrução marcada return
é sublinhada com um erro do compilador:
Type '{ success: true; payload: Payload; }' is not assignable to type 'Result<Payload>'.
Type '{ success: true; payload: Payload; }' is not assignable to type 'Payload extends undefined ? { readonly payload?: unknown; } : { readonly payload: Payload; }'.
Eu me pergunto por que o tipo condicional na mensagem de erro não inclui a success
propriedade? Não deveria ser incluído por ResultBase & …
?
Nota: não vou falar muito sobre o problema subjacente de o compilador não aceitar sua implementação. Tentar atribuir valores a um tipo que envolve um tipo condicional que depende de um parâmetro de tipo genérico quase sempre falhará, porque o compilador não possui a capacidade de raciocínio de ordem superior necessária para entender o que eles significam. Isso está fora do escopo da pergunta feita, então não vou divagar mais.
De modo geral, se você tentar atribuir um tipo
T
a um tipo de interseçãoX & Y
, ele só poderá digitar check ifT
é considerado atribuível a ambosX
eY
. Se o compilador não achar que issoT
pode ser atribuído a pelo menos um deles, ele reportará um erro sobre o quebrado. Portanto, seT
for atribuível,X
mas nãoY
, você poderá esperar uma mensagem de erro comoType 'T' is not assignable to type 'Y'
. Não há necessidade de mencionarX
porque esse não é o problema.Por analogia: se você pedir uma maçã vermelha e eu lhe der uma pêra vermelha, você provavelmente objetará com “mas isso não é uma maçã”, sem sentir necessidade de mencionar “vermelho” em sua frase. Não há nada de errado em dizer “mas esta não é uma maçã vermelha”, mas a palavra “vermelho” não é realmente a origem do problema.
No seu exemplo acima,
T
é{ success: true; payload: Payload; }
,X
é equivalente a{ readonly success: boolean }
eY
é equivalente aPayload extends undefined ? { readonly payload?: unknown; } : { readonly payload: Payload; }
. O compilador fica feliz em ver que issoT
pode ser atribuído aX
. Mas não é possível verificar se issoT
pode ser atribuído aY
. E assim a mensagem de erro não diz nada sobreResultBase &
, porque não é diretamente relevante para o erro.