typescript - 如何强制泛型

标签 typescript

有没有办法在 typescript 中将泛型标记为强制性的?

function onSubmit<Result, Variables>({
    foo,
    bar
  }: {
    foo: Result
    bar: Variables
  }) {
    console.log(foo, bar)
}

// this should not be possible without passing the Generics
onSubmit({ foo: 'foo', bar: 'bar' })

// this works as expected 
onSubmit<number, number>({ foo: 'foo', bar: 'bar' })

Playground

编辑

问题已得到解答,效果非常好。为了更好地理解我为什么要使用它,这里有一个例子。

onSubmit<UpdateUserMutation, UpdateUserMutationVariables>({
  mutation: UpdateUserDocument,
  variables: { id: user.id, user: formData },
  refetchQueries: ['GetUserList'],
  onSuccess: ({ data }) => history.push(`/users/${data.updateUser.id}`),
})

当我省略 <UpdateUserMutation, UpdateUserMutationVariables> 时,我不知道什么data会在我的onSuccess功能。此外,我不知道必须将哪些变量传递给 variables key 。更不用说 IDE 集成了:-)

我当然可以输入 { data }直接,但我认为现在它更舒服,因为我不能“忘记”输入,所以我永远不会使用错误/忘记使用 variables 中的变量对象和 onSuccess功能。

对于好奇的人,这就是我的 onSubmit功能现在看起来:

function onSubmit<
  Result = [Error, 'Please specify the Result type parameter'],
  Variables = [Error, 'Please specify the Variables type parameter'],
  R extends Result = Result,
  V extends Variables = Variables
>({
  mutation,
  variables,
  refetchQueries,
  onSuccess,
}: {
  mutation: DocumentNode
  variables: V
  refetchQueries: ((string | PureQueryOptions)[]) | (string | PureQueryOptions)[]
  onSuccess: (response: FetchResult<R, Record<string, any>, Record<string, any>>) => void
}) {
  client
    .mutate<R>({
      mutation,
      variables,
      refetchQueries,
    })
    .then(response => {
      setErrors({})
      onSuccess(response)
    })
    .catch(handleErrors)
}

最佳答案

故意阻碍类型推断似乎很不幸,但如果我愿意,我可能会这样做:

function onSubmit<
  Result = [Error, "Please specify the Result type parameter"],
  Variables = [Error, "Please specify the Variables type parameter"],
  R extends Result = Result,
  V extends Variables = Variables
>({
  foo,
  bar
}: {
  foo: R
  bar: V
}) {
  console.log(foo, bar)
}

想法是使用generic type parameter defaults让我们更好地控制非推断类型参数会发生什么,并添加一些额外的类型参数以从编译器中删除类型推断站点。 ResultVariables 类型无法从 foobar 属性的传入值中推断出来;它们甚至没有在类型签名中的任何地方被提及。这意味着如果 ResultVariables 不是手动指定的,它们将默认为 [Error, "error message"] 形式的怪异元组类型。那个奇怪的元组类型是缺少 "invalid" type 的解决方法。在 typescript 中。我本可以选择 never,但这样错误消息可能会更含糊。

无论如何 foo 将推断出 R,而 bar 将推断出 V,这必须可分配给 ResultVariables 分别。这意味着如果您不指定 ResultVariables,它们将默认为某种错误类型,然后是 foobar 将被限制为该错误类型,您将得到一个错误:

onSubmit({ foo: 'foo', bar: 'bar' }) // error
//         ~~~         ~~~        
// 'string' not assignable to 'Error, "Please specify the Result type parameter"'
// 'string' not assignable to 'Error, "Please specify the Variables type parameter"'

如果您确实手动指定了ResultVariables,那么RV 将受限于它们(并将默认为它们),因此应该与您以前的版本一样工作:

onSubmit<string>({ foo: 'foo', bar: 'bar' }) // error
//                             ~~~
// 'string' not assignable to 'Error, "Please specify the Variables type parameter"'

onSubmit<number, number>({ foo: 3, bar: 4 }) // okay

onSubmit<number, number>({ foo: 'foo', bar: 'bar' })  // error
//                         ~~~         ~~~
// 'string' not assignable to 'number' x2

这很丑陋,因为语言不希望您这样做...类型推断通常是一件好事。但这是你要求的,所以……是吗?希望有所帮助。祝你好运!

关于typescript - 如何强制泛型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55610260/

相关文章:

javascript - 如何返回 promise ?

选择的 Angular 6 默认值未在 Reactive Form 中被选中

javascript - 什么是胖箭头函数/回调类型?

Angular 2 无法绑定(bind)到 'ngif',因为它不是已知属性

javascript - Typescript with Angular2 - 针对 ES5 会产生错误?

angular - 类型 {} 不可分配给类型 []

javascript - 如何进行运行时转换

javascript - 'package.json' 不在 'rootDir' 之下

reactjs - Ant设计多重选择不接受数组作为默认值

javascript - 如何使用 RxJs 实现分页解决方案?