Skip to content

Feature request: represent Function via generic type parameterized by its return/parameter/this type  #12342

Closed
@HerringtonDarkholme

Description

@HerringtonDarkholme

Background:

With #11929, we can get property type of an object. But we cannot get the return/parameter/this types of a function at compile time.

For single function argument, getting return/parameter type is relative simple by adding generic parameter. But when API is designed to accept a map of functions, it become hard to express in TypeScript.

Using function is a common pattern in vuejs and its derivation.

const component = new Vue({
  computed: {
    getNumber() {
       return 42
    }
  }
})

component.getNumber // 42

By combining mapped types and keyof, we can achieve some compile time types to capture this pattern.

declare interface Vue {
  new <T extends {[k: string]: Function}>(config: {computed: T}): { [K in keyof T]: ReturnType<T[K]>}
}

If only we have a special type called ReturnType.

Another usage is for event handling in most frontend framework. For example, backbone has an event-map syntax for event binding.

book.on({
  "change:author": authorPane.update,
  "change:title change:subtitle": titleView.update,
  "destroy": bookView.remove
});

book.trigger("change:author", author) 
// author should have the parameter type of authorPane.update

Also, with return/parameter/this type support, we can achieve typed bind/apply/call

interface FunctionTyped<ThisType, ArgTypes, RestArg> {
  bind: FunctionTyped<void, [ThisType, ...ArgTypes], RestArg]>
  apply: FunctionTyped<void, [ThisType, [...ArgTypes, ...RestArg]], never>
  call: FunctionTyped<void, [ThisType, ...ArgTypes], RestArg>
}

Note, this would require variadic generic types.

Proposal:

For every function type, we can have a special access key for return type/ parameter type. Parameter type is a tuple type for every argument. If function has rested parameter, parameter type will fallback to array type.

For overloaded function, the return type/parameter type is the union of all corresponding type of overloading signature.

For generic type parameter with function type constraint, the return type is resolved to constraint. the parameter type also resolves to constraint's parameter type (not regarding with variance.) If generic type has no constraint, resolve it to {}.

For Function, the return and parameter type is any, the parameter type is Array<any>.

To access function's parameter type, it might be good to reuse index access type. For example

type Callback = (a: Author) => void
type CallbackArg = Callback["arguments"] // [Author]
type CallbackReturn = Callback["returns"] // void, the access type is arguable

Related

#212
#1773

Edit: I think representing function via typed generic is a more complete solution. But it requires more typing features as prerequisites and rewriting all function type encoding.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Needs InvestigationThis issue needs a team member to investigate its status.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions