条件类型添加了额外的泛型编译器错误

时间:2020-02-25 07:28:59

标签: typescript

根据打字稿官方的Advanced Type部分,我想获得一个如下的自定义类型。

// This is typescript official example of documentation
declare function f<T extends boolean>(x: T): T extends true ? string : number;
let x = f(Math.random() < 0.5) // Type is 'string | number'

// This is what I do
declare function foo<Q, T extends boolean>(x: T): T extends true ? Q : number;

let res = foo<boolean>(true) // failed, expect res is boolean type, but got Compiler error message: Expected 2 type arguments, but got 1

我试图给T一个默认的布尔类型,但是我得到一个错误结果,变量res为number | boolean

我的问题来源来自the sample

更新。

我已经通过根据@ ford04解决方案包装另一个函数解决了我的问题

interface CustomAxiosRequestConfig extends AxiosRequestConfig {
  XFullResponse?: boolean;
}

interface CustomAxiosResponse<T = any> extends AxiosResponse {
  config: CustomAxiosRequestConfig;
}

interface CustomAxiosInstance {
  get<T = any, R = CustomAxiosResponse<T>>(
    url: string,
    config?: CustomAxiosRequestConfig
  ): Promise<R>;
}

let axios = {} as CustomAxiosInstance

interface data {}

const getUser = function<T extends CustomAxiosRequestConfig>(config: T){
  return axios.get<data, T['XFullResponse'] extends true ? data : CustomAxiosResponse<data>>("/getUser", config)
}
// type is Promise<data>
let res1 = getUser({XFullResponse: true})
// type is Promise<CustomAxiosResponse<data>>
let res2 = getUser({XFullResponse: false})

3 个答案:

答案 0 :(得分:1)

您的代码段未收到编译错误。但是无论如何,您应该给2个类型参数,然后它会按预期工作:

declare function foo<Q, T extends boolean>(x: T): T extends true ? Q : number;

let res = foo<boolean, true>(true)     // res is of type boolean (T extends true)
let res = foo<boolean, false>(false)   // res is of type number (T does not extend true)
let res = foo<boolean, boolean>(true)  // res is of type number (T does not extends true)

答案 1 :(得分:1)

对于从此类函数获得的类型安全性,可以对两个通用参数使用推断,如下所示:

let res: boolean = foo(true) // this works
let res_other_type: string = foo(true) // this also works
let res_error: boolean = foo(false) // this is an error

请注意,使用函数签名实际上不可能知道foo实际返回的内容,因此在此处指定类型几乎和从unknown返回foo并进行强制转换一样不安全。到boolean

游乐场here

答案 2 :(得分:0)

我们这里有两个问题

  • 您要定义两个参数通用类型并提供一个(编译错误)
  • 您正在将第二个默认值定义为联合boolean类型

我认为第一个问题是可以理解的,因为当您不提供默认值时,则需要放置参数,您可以理解,由于函数使用两个参数,因此没有默认值意味着两个都需要传递。

第二个问题可能更难以理解,但是您的条件类型会进入两个分支,因为这是distributed in conditional types联合类型的方式。

类型boolean是联合体true | false,这意味着您的条件类型将对联合体的每个元素进行两次评估。因此,让我们看看如何评估两个元素的这种结合-truefalse

  • true extends true ? Q : number //得到Q
  • false extends true ? Q : number //获取号码

结果是所有联合元素上所有评估的联合,因此从true | false中得到Q | number

希望我能向您描述您面临的问题。我无法为您提供更多帮助,因为我不了解您的目标是什么。