Suppose we have the following function:

function test<S, T>(obj: S, prop: keyof S, mapper?: (value: S[keyof S]) => T): S[keyof S] | T {
  return typeof mapper === 'function'
    ? mapper(obj[prop])
    : obj[prop];
}

如果我在没有mapper参数的情况下使用它,则返回值的类型推导不正确:

const value = test({ a: 'stringValue' }, 'a'); // value is of type "unknown"

但如果我提供一个恒等式函数作为第三个参数,则可以正确推导:

const value = test({ a: 'stringValue' }, 'a', x => x); // value is of type "string"

test函数应该如何类型化,以便在不提供mapper参数的情况下,正确推导返回值的类型?

Playground link

推荐答案

只用function overloads

function test<S, T>(obj: S, prop: keyof S): S[keyof S];
function test<S, T>(obj: S, prop: keyof S, mapper: (value: S[keyof S]) => T): T;
function test<S, T>(obj: S, prop: keyof S, mapper?: (value: S[keyof S]) => T): S[keyof S] | T {
    return typeof mapper === 'function'
        ? mapper(obj[prop])
        : obj[prop];
}

const value = test({ a: 'stringValue' }, 'a'); // string

const value2 = test({ a: 'stringValue' }, 'a', x => x);  // string

Playground

Typescript相关问答推荐

ReturnType此索引方法与点表示法之间的差异

如何正确修复TypScript 4.7到4.8升级中的TS 2345编译错误

typescribe警告,explate—deps,useEffect依赖项列表

根据另一个属性的值来推断属性的类型

无法绑定ngModel.条件ngSwitchCase中的错误

类型脚本基于数组作为泛型参数展开类型

通配符路径与每条路径一起显示

TypeScrip界面属性依赖于以前的属性-针对多种可能情况的简明解决方案

如何使默认导出与CommonJS兼容

参数属性类型定义的REACT-RUTER-DOM中的加载器属性错误

CDK从可选的Lambda角色属性承担角色/复合主体中没有非空断言

如何合并两个泛型对象并获得完整的类型安全结果?

正确使用相交类型的打字集

确保对象列表在编译时在类型脚本中具有唯一键

有没有办法取消分发元组的联合?

字符串文字联合的分布式条件类型

如何在Angular /字体中访问API响应的子元素?

仅当类型为联合类型时映射属性类型

有没有一种方法可以防止我的组件包在其中安装样式组件'; node 模块中的s目录

Typescript泛型-键入对象时保持推理