【问题标题】:TypeScript type inference on function type parameter based on its argument type基于参数类型的函数类型参数的 TypeScript 类型推断
【发布时间】:2018-08-28 22:39:01
【问题描述】:

我正在尝试在 TypeScript 中声明一个函数 fun,它使用其类型参数 T 作为可以将哪些键用作另一个函数 context.Foo 的参数的约束:

interface Context<T> {
    Foo(key: keyof T)
}

function fun<T>(provider: (context: Context<T>) => T): number {
    return 1
}

fun<{a: number}>(context => {
    return {a: context.Foo('a')}
})

到目前为止一切顺利,我只能在底部的foo 调用中使用'a' 字面量作为context.Fookey 参数,因为这个调用有一个类型参数声明T{a: number}.

困扰我的是,我实际上将这种内联类型的结构定义为provider 函数体。我只能返回与{a: number} 定义匹配的对象。

我想要实现的是摆脱在调用时显式定义funT 类型的需要,并让类型推断通过对象的结构自行确定该类型。 m 从fun的参数返回(必须是T),像这样:

fun(context => {
    return {a: context.Foo('a')}
})

不幸的是,这以错误结束:

TS2345:“a”类型的参数不能分配给“never”类型的参数。

T 的类型推断失败并退回到never,这在这种情况下绝对没有用。

是否可以以不需要显式设置funT 的方式定义此函数?

【问题讨论】:

  • Context.Foo的返回类型是什么?它总是相同的类型还是通用的?
  • 我认为这是不可能的,即使是即将到来的infer
  • @fathyb 可能是同一类型,比如string

标签: typescript type-inference


【解决方案1】:

我认为没有任何方法可以实现这一点,只要您尝试将Context&lt;T&gt; 绑定到结果的键,编译器就会放弃推理。

由于Foo 总是返回相同的值类型(至少根据我在 cmets 中的理解),您可以只指定类型的键,而不必指定整个类型:

interface Context<K> {
    Foo(key: K): number;
}

function fun<K extends string>(provider: (context: Context<K>) => Record<K, number>): Record<K, number> {
    return provider(null as any);
}

let a = fun<'a'>(context => {
    return { a: context.Foo('a') }
})

【讨论】:

    猜你喜欢
    • 2016-11-01
    • 2012-09-23
    • 2016-12-05
    • 2019-04-26
    • 2021-12-22
    • 1970-01-01
    • 2013-11-10
    • 2020-07-10
    • 2023-02-22
    相关资源
    最近更新 更多