Executando verificação de segurança...
3

[Dica] Como obter a tipagem de um método sem instanciar a classe com TypeScript

Ok, é um tema bem específico. Mas deicidi compartilhar pois quando um tema é muito específico, geralmente é mais difícil de encontrar conteúdo sobre ele. Então vamos começar...

Em qual situação você pode se deparar com esse problema? 💣

No meu caso, eu estava trabalhando com NestJs e usando um módulo de comunicação entre microsserviços com RabbitMQ. Uma característica é que usando uma abordagem de comunicação como essa, não há como o saber o retorno da função, afinal, quem fará a chamada do método do controller será o próprio RabbitMQ dependendo da routing key usada.

Dica de uso para esses casos 🔥

// Aqui eu defino uma classe, que simboliza o controller
class Animal {
  name: string
  constructor(name: string) {
    this.name = name
  }

  setName(name: string) {
    this.name = name
    return this
  }

  makeSound(sound: string, repeat: boolean) {
    console.log(sound)
    if (repeat) console.log(sound)
  }
}

// O tipo MethodGetter é responsável por obter a tipagem do método K de uma determinada classe T
type MethodGetter<T, K extends keyof T> = T[K] extends (...args: any) => any
  ? T[K]
  : any
// O tipo MethodParameter é responsável por obter os argumentos do método K de uma determinada classe T
type MethodParameters<T, K extends keyof T> = Parameters<MethodGetter<T, K>>
// O tipo Args é responsável por permitir a adição de outros parâmetros, além dos próprios parâmetros inferidos pelo método K
type Args<T, K extends keyof T> = [...MethodParameters: MethodParameters<T, K>, aditionalTypings?: any]
// O tipo Return é responsável por obter o retorno do método K de uma determinada classe T
type Return<T, K extends keyof T> = ReturnType<MethodGetter<T, K>>

// A classe messageService simboliza algum módulo de comunicação, como o que eu mencionei acima
class messageService {
  static sendAwait<T, K extends keyof T>(
    routingKey: string,
    ...args: MethodParameters<T, K>
  ): Return<T, K> {
    const res = ('routingKey' + routingKey + 'args:' +
      args) as unknown as Return<T, K>
    return res
  }
}

const { name } = messageService.sendAwait<Animal, 'setName'>('animal@set_name', 'Gatinho Tom')

Tipagem em ação ✨

Note que ao passar a classe Animal, mesmo sem instanciá-la, e indicar o método que será chamado, o TypeScript é capaz de inferir corretamente os argumentos e o retorno da função especificada.

imagem do terminal typescript

Se quiser deixar seu NeoVim assim, confira esse post.

Outras dicas 🚀

Se você curtiu esse post, não deixe de conferir a documentação oficial do TypeScript sobre Utility Types, Indexed Access Types, Keyof Type Operator, que me ajudaram muito, além do TypeScript playground para você poder treinar na Web.

Carregando publicação patrocinada...