'How to type function similar to class typings?

Given the following example:

class Person {
  public greet() {
    return 'hi!'
  }
}

function withPerson(person: Person) {
  function showGreet() {
    console.log(person.greet())
  }

  return { showGreet }
}

const p = new Person()

withPerson(p).showGreet()

(See it on TypeScript Playground)

It's pretty simple to pass about the Person type. After all, it is a class and its definitions are known. However, I wonder how to approach that if instead of class Person I'd have a function Person. For example:

function Person() {
  function greet() {
    return 'hi!'
  }

  return { greet }
}

function withPerson(person: ???) {
  function showGreet() {
    return person.greet()
  }

  return { showGreet }
}

const p = Person()

withPerson(p).showGreet()

I know there are some ways to approach the above, such as with something like:

interface IPerson {
  greet: () => void
}

function Person(): IPerson {
  // ...
}

function withPerson(person: IPerson) {
  // ...
}

(See it on TypeScript Playground)

However, this is an extra I'd have to maintain manually, and not always the typings of Person are trivial. Another take would be:

type TPerson = ReturnType<typeof Person>
function Person() {
  // ...
}

function withPerson(person: TPerson) {
  // ...
}

(See it on TypeScript Playground)

And although the above is way more automatic, it's quite limited. As far as I know, generics are not supported:

type TPerson<T> = ReturnType<typeof Person<T>>

The question

Is class truly the only way to easily reference that [the Person] type out and about?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source