Mapeando objetos com o `in keyof` no Typescript

censuradho

Gustavo Leite

Posted on February 15, 2023

Mapeando objetos com o `in keyof` no Typescript

Neste artigo vamos aprender como funciona o operador in keyof do Typescript, e como ele pode te ajudar a mapear o tipo de objetos, assim evitando de redeclarar propriedades de objeto

Entendendo o in keyof

keyof

Antes de tudo, precisamos saber, o que é o keyof? No Typescript ele é utilizado para obter o nome das propriedades publicas de um tipo.

type Person = {
  age: number
  name: string
}

keyof Person // age | name
Enter fullscreen mode Exit fullscreen mode

in keyof

in é utilizado quando você quer definir uma assinatura de indicie que podemos fornecer para um tipo. Em combinação com o keyof, podemos utilizar para declarar as propriedades que um tipo vai ter baseado nas propriedades de outro tipo.

Podemos criar um objet:

type ToBoolean<T> = {
  [K in keyof T]: boolean
}

type Product = {
  name: string
  price: number
}

const hasProductProperties: ToBoolean<Product> = {
 name: true,
 price: false
}
Enter fullscreen mode Exit fullscreen mode

Elevando o seu conhecimento.

extends keyof

extends basicamente funciona como em classes, você extende propriedades de um tipo. Em combinação com o keyof, você restringe os valores que podem ser passados para um tipo genérico.

function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] {
  return obj[key]
}

const person: Person = {
  age: 26,
  name: "Gustavo",
}


const name = getProperty(person, "name")
Enter fullscreen mode Exit fullscreen mode

Nesse exemplo, eu estou definindo a função getProperty, que recebe como primeiro parametro um objeto, e segundo a chave desse objeto, retornando o valor dessa propriedade.

Combinando o in keyof e o extends keyof

// bloco 1
type Query<T, K extends keyof T> =  {
  $eq?: T[K] | Array<T[K]>
  $ne?: T[K] | Array<T[K]>
}

// bloco 2
type WhereParams<T> = {
  [K in keyof T]?: T[K] | Query<T, K>
};

// bloco 3
type Product = {
  name: string
  price: number
}

// bloco 4
const myQuery: WhereParams<Product> = {
  name: {
    $eq: 'Gustavo'
  }
}

Enter fullscreen mode Exit fullscreen mode
  • Bloco 1:

Estou dizendo que os filtros devem ter o tipo da devida propriedade do objeto que eu passar.

exemplo com o Product, somente string | number

// erro
const myQuery: Query<Product, keyof Product> = {
  $eq: false
}

// sucesso

const myQuery2: Query<Product, keyof Product> = {
  $eq: 'uma string'
}

Enter fullscreen mode Exit fullscreen mode
  • Bloco 2:

O WhereParams recebe um tipo, e as propriedades dele, irão ser assinadas com as chaves do tipo que eu passei como generic. Sendo o valor desse objecto, do tipo da propriedade em específico, ou um objeto de queries desse mesmo tipo.

  • Bloco 3:

Definição da entidade Produto

  • Bloco 4:

Instancia da query baseada nos filtros da entidade Product.

Conclusão

Existem maneiras de deixar nosso código muito mais inteligênte elevando o auto complete à um outro nível. Com o in keyof, podemos criar interfaces genéricas mapeando toda cadeia de propriedades, baseando tipos em outros tipos, evitamos a repetição de código.

Referências

💖 💪 🙅 🚩
censuradho
Gustavo Leite

Posted on February 15, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related