【问题标题】:Conditional type on generic function: Type is not assignable泛型函数的条件类型:类型不可分配
【发布时间】:2020-07-08 12:54:49
【问题描述】:

我正在尝试限制泛型函数的返回类型。 (示例为简单起见,请忽略函数的实际“有用性”)。

type MyReturnType<T> = T extends string ? number : Function;
type Input = string | number;
function myFn<T extends string | number>(input: T): MyReturnType<T> {
  return typeof input === 'string' ? 100 : (() => {});
}

但是return 语句会导致打字稿错误——

Type '100 | (() => void)' is not assignable to type 'MyReturnType<T>'.
  Type '100' is not assignable to type 'MyReturnType<T>'.

——这让我很困惑。据我了解,MyReturnType&lt;T&gt; 只能解析为数字或函数。 100怎么不能赋值?我这里有什么问题吗?编译器想告诉我什么?

我觉得答案可能在 docs for conditional types 中,但我找不到它(老实说,这里的文档的某些部分让我有点不知所措)。有人可以向我解释一下这个 sn-p 中发生了什么吗?


(TS 3.8.3)

【问题讨论】:

  • @Lesiak 感谢您的评论!非布尔值实际上也会出现问题,我调整了问题以反映这一点。我阅读mhegazy's comment on that issue 的方式,这是编译器的设计限制,现在需要类型转换来避免它。你同意这个观点吗?你愿意回答吗(因为你挖出了这个问题)?否则,我会这样做。

标签: typescript generics typescript-generics


【解决方案1】:

这里的实际工作解决方案是使用重载:

type Input = string | number;
function myFn(input: string): number
function myFn(input: number): Function
function myFn(input: Input): number | Function {
    return typeof input === "string" ? 100 : () => {}
}

只要确保你写了一个来涵盖每一种输入类型的可能性。在我的例子中,我的论点有 5 种可能的类型(包括 2 个联合),我必须这样写:

type Value = string | number | null
export function divBy10toPow(value: string, power: number): number
export function divBy10toPow(value: null, power: number): null
export function divBy10toPow(value: number, power: number): number
export function divBy10toPow<T extends number | null>(value: T, power: number): T
export function divBy10toPow<T extends string | null>(value: T, power: number): T extends string ? number : null
export function divBy10toPow(value: Value, power: number): Value {
    return value === null
        ? null
        : BigNumber(value)
            .div(10 ** power)
            .toNumber()
}

您必须考虑到string | nullnumber | null 的具体联合,否则它不会正确输入您的返回值。

【讨论】:

    【解决方案2】:

    看起来像编译器限制类型缩小到联合类型:

    Type 'true' is not assignable to type 'T2 extends keyof T1 ? true : false' #22735

    【讨论】:

      猜你喜欢
      • 2019-10-13
      • 2019-08-11
      • 2020-01-02
      • 2018-09-19
      • 2018-11-20
      • 2020-03-21
      • 2021-11-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多