如何为具有重叠参数的函数定义一个通用接口/类型定义?

huangapple go评论77阅读模式
英文:

How to define a common interface/type definition for functions with overlapping parameters?

问题

以下是翻译好的部分:

我有多个具有重叠参数的函数。例如,考虑两个函数:

为了减少重复,我一直在使用以下两种方法,但都不是理想的方法:

方法1

type Params = {
  p1?: string,
  p2?: string,
  p3?: string
}

fn1({p1, p2}: Params)
fn1({p2, p3}: Params)

这种方法的问题是允许调用函数而不提供必需的参数。

方法2

type Params = {
  p1: string,
  p2: string,
  p3: string
}
fn1({p1, p2}: Omit<Params, 'p3'>)
fn1({p2, p3}: Omit<Params, 'p1'>)

这种方法的问题是它显示了与函数不相关的参数。

是否有更好的方法来解决这个问题?

英文:

I have multiple functions with overlapping params. For example, take two functions as

fn1({p1, p2}: {p1: string, p2: string})()
fn2({p2, p3}: {p2: string, p3: string})()

To reduce duplication, I have been using following two methods, but none of them are ideal

Method 1
type Params = {
  p1?: string,
  p2?: string,
  p3?: string
}

fn1({p1, p2}: Params)
fn1({p2, p3}: Params)

Issue with this method is it allows calling the function without the required parameters

Method 2
type Params = {
  p1: string,
  p2: string,
  p3: string
}
fn1({p1, p2}: Omit&lt;Params, &#39;p3&#39;&gt;)
fn1({p2, p3}: Omit&lt;Params, &#39;p1&#39;&gt;)

Issue with this method is it shows parameters which are not in focus for the function.

Is there a better method to do it ?

答案1

得分: 1

我已经创建了一个Args类型,它允许简单地选择可选属性以用作函数参数。

interface AllArgs {
  num: number,
  str: string,
  null: null,
}

type Pure<T> = { [K in keyof T]: T[K] }
type ReplaceEnd<S, L extends string> = S extends `${infer F}${L}` ? F : S
type Args<K extends keyof AllArgs | `${keyof AllArgs}?`, Extend extends Record<any, any> = {}> =
  | Pure<
    & Pick<AllArgs, K & keyof AllArgs>
    & Partial<Pick<AllArgs, ReplaceEnd<K, '?'>> & keyof AllArgs>
    & Extend
  >;

type y = Args<'num' | 'str?', { foo: true }>
//   ^?
// type y = { num: number; str?: string; foo: true; }

function f({ num, foo, str }: Args<'num' | 'str?', { foo: 'bar' }>) {
  console.log(num)
  //          ^?
  // (parameter) num: number
  console.log(str)
  //          ^?
  // (parameter) str: string | undefined
  console.log(foo)
  //          ^?
  // (parameter) foo: "bar"
}

(如果有更好的方法,请@我,我也使用这个概念)

英文:

I've made Args type that allows simply pick optionable properties for using as function arguments.

interface AllArgs {
  num: number,
  str: string,
  null: null,
}

type Pure&lt;T&gt; = { [K in keyof T]: T[K] }
type ReplaceEnd&lt;S, L extends string&gt; = S extends `${infer F}${L}` ? F : S
type Args&lt;K extends keyof AllArgs | `${keyof AllArgs}?`, Extend extends Record&lt;any, any&gt; = {}&gt; =
  | Pure&lt;
    &amp; Pick&lt;AllArgs, K &amp; keyof AllArgs&gt;
    &amp; Partial&lt;Pick&lt;AllArgs, ReplaceEnd&lt;K, &#39;?&#39;&gt; &amp; keyof AllArgs&gt;&gt;
    &amp; Extend
  &gt;;

type y = Args&lt;&#39;num&#39; | &#39;str?&#39;, { foo: true }&gt;
//   ^?
// type y = { num: number; str?: string; foo: true; }

function f({ num, foo, str }: Args&lt;&#39;num&#39; | &#39;str?&#39;, { foo: &#39;bar&#39; }&gt;) {
  console.log(num)
  //          ^?
  // (parameter) num: number
  console.log(str)
  //          ^?
  // (parameter) str: string | undefined
  console.log(foo)
  //          ^?
  // (parameter) foo: &quot;bar&quot;
}

(If there is a betted way please @ me, I also use this concept)

huangapple
  • 本文由 发表于 2023年7月7日 02:38:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/76631682.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定