Typescript,如何根据函数参数约束类型?

nzkunb0c  于 2023-05-23  发布在  TypeScript
关注(0)|答案(1)|浏览(207)

如何使useWatchProps回调函数参数与第一个参数相对应

type KeysToValues<O extends Record<string, any>, K> = K extends [
  infer G,
  ...infer L
]
  ? G extends keyof O
    ? [O[G], ...KeysToValues<O, L>]
    : []
  : []

function useWatchProps<
  O extends Record<string, any>,
  K extends keyof O = keyof O,
  T extends K | K[] = K | K[]
>(
  keys: T,
  callback: (values: T extends K ? O[K] : KeysToValues<O, K>) => void
) {}

useWatchProps<{ a: number; b: string }>('a', (a) => {
  a // number
})
useWatchProps<{ a: number; b: string }>(['a', 'b'], ([a, b]) => {
  a // number
  b // string
})

如何通过关键点约束T

dgjrabp2

dgjrabp21#

由于您没有传递T,它会自动转换为您指定的默认值。不幸的是,我们不能只指定所需参数的一部分;因此,我可以建议让useWatchProps只接受O并返回另一个函数。用法如下所示:

useWatchProps<{ a: number; b: string }>()('a', (a) => {
  a; // number
});

我们还需要将T更改为const类型参数,以避免编译器将T转换为并集。这将导致T的所有检查变为readonly some_array/some_tuple
修改:

type KeysToValues<O extends Record<string, any>, K> = K extends readonly [
  infer G,
  ...infer L,
]
  ? G extends keyof O
    ? [O[G], ...KeysToValues<O, L>]
    : []
  : K

实施:

function useWatchProps<O extends Record<string, any>>() {
  return <const T extends keyof O | readonly (keyof O)[]>(
    keys: T,
    callback: (values: T extends keyof O ? O[T] : KeysToValues<O, T> ) => void,
  ) => {};
}

用途:

useWatchProps<{ a: number; b: string }>()('a', (a) => {
  a; // number
});
useWatchProps<{ a: number; b: string }>()(['a', 'b'] , ([a,b]) => {
  a; // number
  b; // string
});

Playground

相关问题