AS: A ordem de propriedade do objeto em JS é um tópico muito complicado . Para minhas intenções e propósitos, apenas a ordem de inserção importa.
TL;DR: Existe uma maneira de declarar uma propriedade de objeto em JavaScript sem atribuir um valor a ela, para que, quando a propriedade for definida posteriormente, ela ainda apareça antes na ordem de inserção?
const user = { name: unset, age: 42 }
Tenho um conjunto de funções assíncronas, cada uma retornando um valor associado a uma chave única. Elas são então invocadas em paralelo para construir um objeto com pares chave-valor usados como entradas (propriedades). Algo assim:
const props = {}
const propsSet = getters.map(async ([key, getValue]) => {
props[key] = async getValue()
})
await Promise.all(propsSet)
return props
Como tudo isso é assíncrono, a ordem das propriedades em props
está em todo lugar: às vezes recebo { foo: …, bar: … }
, às vezes { bar: …, foo: … }
. Eu poderia consertar isso associando cada getter a um número de sequência. Mas uma solução muito mais fácil é apenas iniciar as propriedades o mais rápido possível; devido a como o loop de eventos funciona, isso é basicamente uma garantia de que as propriedades de props
serão ordenadas da mesma forma que em getters
:
const propsSet = getters.map(async ([key, getValue]) => {
props[key] = null // or any other initialization token
props[key] = await getValue()
})
Em JS puro, isso é algo perfeitamente normal de se fazer, mas em TypeScript isso geralmente é um erro do compilador (já que um "token de inicialização" arbitrário não pode ser atribuído a propriedades estritamente tipadas de props
); então, tenho que silenciar o compilador, o que não gosto de fazer:
values[key] = null! // non-null assertion operator
Eu preferiria que a propriedade não fosse realmente definida no objeto, mas que um "slot" fosse disponibilizado para ela. Percebi que o que eu basicamente preciso é muito similar a declarar variáveis separadamente de inicializá-las, – como no estilo JS old-school:
var value1, value2
value1 = 42
value2 = 17
Existe alguma maneira existente ou futura (proposta) de declarar propriedades de objetos em JavaScript sem inicializá-los?
Note que não estou perguntando sobre maneiras de ordenar propriedades. Há muitas estratégias para fazer isso, incluindo o uso dos números de sequência mencionados anteriormente (por exemplo, índices de array).
Não. Não há declarações (de tipo?) em tempo de execução. Você só pode criar uma propriedade de objeto, por atribuição (em uma declaração) ou inicialização (em um literal de objeto). Ou a propriedade existe, com um valor 1 , ou ela não existe de forma alguma. O valor padrão de variáveis ou propriedades não definidas de outra forma seria
undefined
, não há valor "não definido" (ou ausência de um valor).A abordagem idiomática do TS para (não) inicializar uma propriedade
undefined
independentemente do seu tipo declarado seria usar uma asserção não nula:Mas isso é basicamente mentir sobre o tipo de
props
, o objeto não é realmente utilizável até que sua inicialização assíncrona termine e seu tipo deve refletir isso. Então, em vez de afirmar,Object.create(null) as Record<GroupName, Group>
você deve usar umPartial
tipo e afirmar o tipo de resultado esperado somente quando todas as propriedades forem realmente inicializadas:Uma abordagem ainda melhor, no entanto, seria adiar a criação do objeto até que todos os valores de propriedade estejam disponíveis. Dessa forma, não há objetos "incompletos" que precisem ser digitados em nenhum momento. No seu caso, isso seria
1: Assumindo uma propriedade de dados. Pode-se definir uma propriedade de acesso sem getter, ou um getter que sempre lança. Você pode fazer isso e, subsequentemente, convertê-lo em uma propriedade de dados, mas eu desaconselho isso. É muito complicado, ineficiente e também não melhora os tipos.