首页 > 解决方案 > 根据函数参数推断回调参数类型

问题描述

    type SeveralTypes = type0 | type1 | type2;
    function funTypes<T extends SeveralTypes>(info: T, callback: (obj: T extends type2 ? number : string) => void) {
        if (isType0(info)) {
            return callback("passAstring");  // TS Warn: Argument of type '"passAstring"' is not assignable to parameter of type 'T extends boolean ? number : string'

        } else if (isType1(info)) {
            return callback("passAstring"); // TS Warn: Argument of type '"passAstring"' is not assignable to parameter of type 'T extends boolean ? number : string'

        } else {
            return callback(1001); // TS Warn: Argument of type '1001' is not assignable to parameter of type 'T extends boolean ? number : string'
        }
    }

    funTypes(1, (d) => { });       // Typeof d --> string
    funTypes("str", (d) => { });   // Typeof d --> string
    funTypes(false, (d) => { });   // Typeof d --> number

当我使用这个函数时,参数回调的推断类型是正确的。但是 TS 在分配参数时会出现问题。是否有另一种输入回调参数的方法?

标签: typescripttype-inference

解决方案


这里有几个问题。主要的是缩小一个变量(info在这种情况下)永远不会对另一个变量()的类型产生任何影响callback。还有一个问题是,通常仍然包含未解析类型参数的条件类型通常很难让编译器推理,因此由于T未知,并且您的函数需要一个依赖于的参数T,typescript 会做安全的事情,而不是让您用作参数number或者string

解决这个问题的常用方法是使用类型断言或我的首选方法,使用通用公共签名和更宽松的实现签名(请注意,确保条件类型中的逻辑被复制到实现,这里没有编译器的帮助)

type SeveralTypes = type0 | type1 | type2;
function funTypes<T extends SeveralTypes>(info: T, callback: (obj: T extends type2 ? number : string) => void): void
function funTypes(info: SeveralTypes, callback: (obj: number | string) => void) {
  if (isType0(info)) {
    return callback("passAstring");

  } else if (isType1(info)) {
    return callback("passAstring");

  } else {
    return callback(1001); 
  }
}

funTypes(1, (d) => { });       // Typeof d --> string
funTypes("str", (d) => { });   // Typeof d --> string
funTypes(false, (d) => { });   // Typeof d --> number

游乐场链接


推荐阅读