Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Separate and export the return types of function definitions #3422

Closed
nspaeth opened this issue Aug 6, 2024 · 3 comments
Closed

Separate and export the return types of function definitions #3422

nspaeth opened this issue Aug 6, 2024 · 3 comments
Labels
enhancement New feature or request

Comments

@nspaeth
Copy link
Contributor

nspaeth commented Aug 6, 2024

What is the problem this feature would solve?

  1. I sometimes want to use the return type of an Effect function but do not have direct access to the type.
  2. Reading Effect source is sometimes made more difficult due to the complex types, especially when the return types are duplicated for dual functions.

What is the feature you are proposing to solve the problem?

I propose that the return types be refactored out of the definition so that they can be easily re-used.
For example, the current Struct.pick is defined by:

export const pick: {
  <Keys extends Array<PropertyKey>>(
    ...keys: Keys
  ): <S extends { [K in Keys[number]]?: any }>(s: S) => MatchRecord<S, { [K in Keys[number]]?: S[K] }, Simplify<Pick<S, Keys[number]>>>
  <S extends object, Keys extends Array<keyof S>>(
    s: S,
    ...keys: Keys
  ): MatchRecord<S, { [K in Keys[number]]?: S[K] }, Simplify<Pick<S, Keys[number]>>>
} = dual(
  (args) => Predicate.isObject(args[0]),
  <S extends object, Keys extends Array<keyof S>>(s: S, ...keys: Keys) => {
    const out: any = {}
    for (const k of keys) {
      if (k in s) {
        out[k] = (s as any)[k]
      }
    }
    return out
  }
)

But it would be helpful to be re-defined as:

export const pick: {
  <Keys extends Array<PropertyKey>>(...keys: Keys): <S extends { [K in Keys[number]]?: any }>(s: S) => pick<S, Keys>
  <S extends object, Keys extends Array<keyof S>>(s: S, ...keys: Keys): pick<S, Keys>
} = dual(
  (args) => Predicate.isObject(args[0]),
  <S extends object, Keys extends Array<keyof S>>(s: S, ...keys: Keys) => {
    const out: any = {}
    for (const k of keys) {
      if (k in s) {
        out[k] = (s as any)[k]
      }
    }
    return out
  }
)
export type pick<S extends object, Keys extends Array<keyof S>> = MatchRecord<S, { [K in Keys[number]]?: S[K] }, Simplify<Pick<S, Keys[number]>>>

This has the added bonus of making the source easier to read by reducing the complexity of the type definition and assigning human readable names.

What alternatives have you considered?

  1. Copy & paste the type
    a. This would be noisy which reduces readability.
    b. It is error-prone.
    c. It is likely to become out-of-sync.
    d. Sometimes the return types use other helper types that are also not exported, further complicating the process.

  2. Use ReturnType<typeof Struct.pick<typeof myStruct, typeof pickKeys>
    a. This is also noisy, reducing readability.
    b. ReturnType relies on type inference through conditional types, which is not as reliable (or performant) as direct type declarations.

@nspaeth nspaeth added the enhancement New feature or request label Aug 6, 2024
@fubhy
Copy link
Member

fubhy commented Aug 7, 2024

I don"t think that this is practical. It is also not possible in many cases (e.g. for overloaded function declarations) in a way that would keep the perceived simplicity / readability benefits. Personally, I also don"t find it more readable. This is more a matter of taste / personal opinion, but I find that it adds an additional indirection where one has to jump back and forth to fully ready the type declaration.

Could you maybe elaborate what your concrete use-case is? I"ve personally not really had this need except for a few rare cases maybe.

@mikearnaldi
Copy link
Member

also don"t think it"s practical nor useful

@mikearnaldi
Copy link
Member

closing due to inactivity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants